10

I need to update my animations per frame, on iOS I have CADisplayLink, on WinPhone I have CompositionTarget, but how do I do that on Android?

Currently I'm using a Timer alongside a Handler, but I believe there is a way to sync the callback with the refresh rate.

Franci Penov
  • 74,861
  • 18
  • 132
  • 169
horeaper
  • 361
  • 1
  • 16

2 Answers2

3

The most direct equivalent I'm aware of is Choreographer (as of API 16).

It looks like how your animations are written determines the best way to sync it. Choreographer is not generally useful. Choreographer is useful if your animation is written outside of the "animation framework" which AFAIK includes ViewPropertyAnimator and ... maybe XML defined animations? Exactly what is undocumented.

Choreographer looks like it's mainly useful for syncing GLSurfaceView animations.

nmr
  • 16,625
  • 10
  • 53
  • 67
  • 1
    FWIW, it seems like Android's UI framework renders lock-step with GLSurfaceView. My guess is SurfaceFlinger performs a blocking frame dequeue from each before compositing output frames. – nmr Nov 16 '16 at 19:47
2

Hm, looks like ViewTreeObserver might help you there. Try this code:

final ViewTreeObserver vto = myView.getViewTreeObserver();
vto.addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
    @Override
    public void onDraw() {
        // Do whatever you need to do...
    }
});

Couple of notes:

  • onDraw has bunch of limitations of what you can do in it. Specifically, you can't modify the view tree. If that's something you need to do, look at the ViewTreeObserver.OnPreDrawListener instead.
  • camera preview and media playback are drawn on a separate path, and most likely are not synchronized with this listener, so you wan't be able to use it to do stuff in sync with the individual frames.
mvds
  • 45,755
  • 8
  • 102
  • 111
Franci Penov
  • 74,861
  • 18
  • 132
  • 169
  • 3
    This differs from `CADisplayLink` in that you only get called back if the view is drawn, which happens only if the view is invalidated, *after* the drawing is done. In contrast, `CADisplayLink` is called on every frame drawn. To mimic `CADisplayLink` I do the above, and call `invalidate()` in my custom view's `onDraw()` method as well. – mvds May 05 '13 at 20:02