Animation at the beginning of activity jumps
Asked Answered
N

2

10

I am working on animating custom Views for my Android app. I have accomplished this via Property Animations and calling invalidate() on the View in the onAnimationUpdate() callback, as per https://developer.android.com/guide/topics/graphics/prop-animation.html:

Depending on what property or object you are animating, you might need to call the invalidate() method on a View to force the screen to redraw itself with the updated animated values. You do this in the onAnimationUpdate() callback.

My problem is that when these animations are run at the beginning of a newly launched Activity, they skip frames at the beginning, causing them to jump very noticeably. I have tried both:

  1. Starting the animation immediately from the Activity's onCreate() method
  2. Starting the animation upon the OnGlobalLayout() callback using the ViewTreeObserver of the Activity's root view.

I did the latter since I thought maybe the animation was invoked before the layout had been finalized, but the result is the same.

With logs, I determined that the onAnimationUpdate() callback is called consistently throughout the animation (that is, every 10-20 ms or so, from start to end). onAnimationUpdate() simply calls invalidate(), which should force the View to redraw itself, ideally immediately (but the documentation only claims this happens "at some point in the future"). That seems to be precisely the problem: onDraw() is only called once or twice at the very start before not being called for about 250 ms. After this, it resumes being called every 10-20 ms, as it should have the whole time. But that block of time causes very noticeable lag in the animation.

To be clear, this problem only happens at the beginning of the Activity. If I simply set a 300 ms delay before starting the animation, it runs smoothly all the way through. But I don't like that solution, since it's hacky. It seems the problem is that onDraw() is not called immediately upon invalidate() near the beginning of the Activity. But, I can't figure out why this is, what's blocking onDraw(), or how to fix it at all.

I found only this StackOverFlow thread: Animation at the beginning of activity skips frames where the poster has the identical problem. The basic code is there and the videos make the problem clear. I can post my code too, but I think that the fact that the problem appears in the most basic test app shows that there's something else going on.

Niels answered 22/6, 2016 at 4:12 Comment(0)
D
6

Since there are no codes attached, I'm assuming you have some transition animation to the activity. If this is the case, it might cause the problem.Since there are two animations running simultaneously. Disable the transition and give it try.

startActivity(intent);
getActivity().overridePendingTransition(0, 0); 
Disbranch answered 29/6, 2016 at 12:19 Comment(2)
I had no custom transition animation but there is one on by default. Disabling the transition animation as suggested did indeed fix the animation. Since this is jarring, however, I found the following Activity callback: onEnterAnimationComplete(). The problem is officially explained there: "Activities cannot draw during the period that their windows are animating in." Starting my animations from that callback fixes the issue.Niels
@Niels The method is there but ... only available from API 21. By the way, it's not working all the time.Asta
M
2

It sounds like your draw loop UI thread is getting starved.

I'd use traceview to be sure that there aren't any methods blocking your draw calls. http://tools.android.com/tips/traceview

This should help you determine what's being invoked instead of the onDraw method.

Mcquillin answered 30/6, 2016 at 22:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.