Upgrade to Pro — share decks privately, control downloads, hide ads and more …

I Can Animate and So Can You

Daniel Lew
November 15, 2013

I Can Animate and So Can You

A talk about View animations on Android.

Original Keynote files (with animations): https://db.tt/qnUnoHpF

Daniel Lew

November 15, 2013
Tweet

More Decks by Daniel Lew

Other Decks in Programming

Transcript

  1. I Can Animate and So
    Can You
    Daniel Lew, Nov. 15 2013

    View Slide

  2. What I Used To Do
    • Cross fades
    • Graph scale

    View Slide

  3. Typical Animation
    Demo

    View Slide

  4. What Can Be Done

    View Slide

  5. Revelations
    (I was thinking about animations all wrong)

    View Slide

  6. Revelation #1
    Every animation is unique

    View Slide

  7. Revelation #2
    Animation code is not pretty

    View Slide

  8. Revelation #3
    Animations first
    Animate

    View Slide

  9. Revelation #4
    Animate for 4.x+

    View Slide

  10. Ditch 2.x
    • Poor performance
    • Can't use modern tricks
    • Backup: NineOldAndroids

    View Slide

  11. Ditch 3.x
    • Tiny userbase
    • ViewPropertyAnimator -
    Introduced 3.1
    • TextureView -
    Introduced 4.0

    View Slide

  12. Building Animations
    • Figure out what
    attributes to animate
    • Design View hierarchy
    • Measure attribute start/
    end values
    • Setup and run animators

    View Slide

  13. View Attributes
    • Basic animation attributes
    • Translation
    • Scale
    • Rotation
    • Alpha
    • Custom attributes can be added

    View Slide

  14. Determining Attributes
    • What needs to happen?
    • What can be faked?

    View Slide

  15. Determining Attributes
    • Alpha - every element
    • Translate - every row
    • Translate - details
    header/footer
    • Scale - details rows (a
    hardcore fake)
    • Fading background - not
    needed!

    View Slide

  16. View Hierarchy
    • Animation informs View
    hierarchy
    • Rows go underneath
    split action bar
    • Classic problem: Views
    cannot animate outside
    their parent's bounds

    View Slide

  17. Measuring Views
    • Problem: Views not measured until
    sometime after inflation
    • ViewTreeObserver - lets you know when a
    View has been measured
    • OnGlobalLayoutListener
    • OnPreDrawListener
    • Can cancel drawing before it happens

    View Slide

  18. ViewTreeObserver
    Pattern
    final View view = findViewById(R.id.view);
    view.getViewTreeObserver().addOnPreDrawListener(new
    OnPreDrawListener() {
    public boolean onPreDraw() {
    view.getViewTreeObserver().removeOnPreDrawListener(this);
    // Measure here!
    return true;
    }
    });

    View Slide

  19. Measuring "After"
    • Align to other existing Views
    • Create invisible "dummy" Views to animate
    towards
    • Start in the correct position, animate
    towards it

    View Slide

  20. Running Animators
    • ObjectAnimator - animate!
    • AnimatorSet - synchronize multiple
    Animators
    • AnimatorListener - setup and cleanup
    • Canceling Animators w/ reverse()

    View Slide

  21. Property Animators
    • Generic animation framework
    • Animates any value over time
    • Not limited to just visual animations
    • Basic building block for most animations

    View Slide

  22. ObjectAnimator
    • Type of property animator
    • Used for animating essential View properties
    • Position (or translation)
    • Rotation
    • Scale
    • Alpha
    • Can be used on custom View properties

    View Slide

  23. ObjectAnimator
    // Uses built-in property to avoid reflection
    ObjectAnimator.ofFloat(myView, View.ALPHA, 1).start();
    // Alternative, with PropertyValuesHolder
    // Depends on setAlpha() and getAlpha()
    PropertyValuesHolder pvh =
    PropertyValuesHolder.ofFloat("alpha", 0, 1);
    ObjectAnimator.ofPropertyValuesHolder(mySecondView,
    pvh);

    View Slide

  24. AnimatorSet
    ObjectAnimator one = ObjectAnimator.ofFloat(view1,
    "alpha", 1);
    ObjectAnimator two = ObjectAnimator.ofFloat(view2,
    "alpha", 1);
    AnimatorSet set = new AnimatorSet();
    set.playTogether(one, two);
    set.start();

    View Slide

  25. Animator Listeners
    ObjectAnimator anim = ObjectAnimator.ofFloat(view,
    "alpha", 1);
    anim.addListener(new AnimatorListenerAdapter() {
    public void onAnimationEnd(Animator animation) {
    // Clean-up code here
    }
    });
    anim.start();

    View Slide

  26. Reversing Course
    • ValueAnimator.reverse()
    • Useful for smoothly canceling an animator
    • Can recursively traverse AnimatorSet for
    ValueAnimators

    View Slide

  27. Performance
    • Choppy animation == painful
    • Performance cannot be an afterthought
    • Smooth animations informs View structure

    View Slide

  28. Performance
    Breakdown
    • Layout - size/location of Views
    • Draw - what's inside Views
    • Render - pushing it on screen

    View Slide

  29. Layout Performance
    • Initiated by
    View.requestLayout()
    • Slow - avoid at all costs
    • Can sneak up on you

    View Slide

  30. Draw Performance
    • Initiated by
    View.invalidate()
    • Acceptable during
    animations
    • Can be optimized with
    layers

    View Slide

  31. Render Performance
    • Initiated every time
    pixels are put on screen
    • Varies with pixel count/
    speed of device
    • Try to reduce overdraw

    View Slide

  32. Profiling

    View Slide

  33. Demo: Profiling Movies

    View Slide

  34. Profile GPU Rendering
    • Blue - Draw
    • Red - Process
    • Orange - Execute
    • Green line - your goal

    View Slide

  35. Show GPU Overdraw
    • Shows overdrawn pixels
    • Best to worst: nothing,
    blue, green, red, dark red
    • Some overdraw
    necessary, but reduce if
    possible

    View Slide

  36. Show Hardware Layer
    Updates
    • Flashes green on HW
    layer redraw
    • If constantly flashing,
    you're doing something
    wrong!

    View Slide

  37. TraceView
    • Breakdown of methods
    • May skew results

    View Slide

  38. Systrace
    • Measures everything on
    the system
    • Much more accurate
    than TraceView
    • Bigger picture view

    View Slide

  39. OpenGL Traces

    View Slide

  40. Profile Warning
    • Can be inaccurate
    • One profiling tool at a time, please
    • Profile multiple devices

    View Slide

  41. Animation
    Optimizations

    View Slide

  42. Layers
    • Layers store drawn
    Views for reuse
    • Reduces drawing during
    animation
    • Reduces overdraw
    during animation

    View Slide

  43. Layer Pattern
    final View myView = findViewById(R.id.my_view);
    myView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    myView.animate()
    .translationX(50)
    .setListener(new AnimatorListenerAdapter() {
    public void onAnimationEnd(Animator animation) {
    myView.setLayerType(View.LAYER_TYPE_NONE, null);
    }
    })
    .start();

    View Slide

  44. Layer Caveats
    • Warning: redrawing a
    layer is *slower* than
    non-layer
    • DisplayLists will rebuild
    layers when necessary
    • Layering simple Views
    just hurts performance

    View Slide

  45. Avoiding Layouts
    • Layouts == slow!
    • Layouts happen often
    • Subclass Views to block layouts

    View Slide

  46. ImageView Blocking
    Layout
    public void setIsFixedSize(boolean isFixedSize) {
    mIsFixedSize = isFixedSize;
    }
    public void setImageBitmap(Bitmap bm) {
    mBlockMeasurement = true;
    super.setImageBitmap(bm);
    mBlockMeasurement = false;
    }
    public void requestLayout() {
    if (!mBlockMeasurement || !mIsFixedSize) {
    super.requestLayout();
    }
    }

    View Slide

  47. Alpha Compositing
    • Needed for Views w/
    multiple internal layers
    • Renders into offscreen
    buffer before fade
    • Slower, obviously

    View Slide

  48. hasOverlappingRendering()
    • New in API 16
    • Off-screen rendering not required for all
    Views
    • Return false for any single-layer custom
    View

    View Slide

  49. TextView's Overlapping
    Rendering
    @Override
    public boolean
    hasOverlappingRendering() {
    return (getBackground() != null
    || mText instanceof Spannable
    || hasSelection());
    }

    View Slide

  50. Other Animation Tools

    View Slide

  51. ViewPropertyAnimator
    • Retrieved via View.animate()
    • Shortcut for simple animations
    • Better performance when manipulating
    multiple values of a View
    • Cons: no easy way to reverse
    • Cons: no way to group animations

    View Slide

  52. ViewPropertyAnimator
    myView.animate()
    .alpha(1)
    .translationX(50)
    .setDuration(500)
    .start();

    View Slide

  53. Tween Animations
    • The original, so backwards compatible
    • Sometimes necessary
    • Fragment transactions
    • Limited to simple property changes
    • Not as rich as property animators

    View Slide

  54. Interpolators
    • Controls the speed of the animation
    • Accelerating
    • Decelerating
    • Overshoot
    • Makes animations feel "right"

    View Slide

  55. ActionBar Animations
    • ActionBar.show()
    • ActionBar.hide()
    • android:windowActionBarOverlay
    • Duration not customizable

    View Slide

  56. SurfaceView and
    TextureView
    • Generic drawing utilities
    • Great for constantly
    animated View

    View Slide

  57. SurfaceView vs.
    TextureView
    • TextureView is API 4.0+
    • TextureView only works in HW
    accelerated windows
    • TextureView can, itself, be animated
    • SurfaceView uses hack and acts weird
    • TextureView is not as fast as SurfaceView

    View Slide

  58. Activity Window
    Animations
    • Custom tween animations between
    Activities
    • Limited to full-screen transitions
    • Activity.overridePendingTransition()
    • android:windowAnimationStyle

    View Slide

  59. Fragment Animations
    • Custom animations during Fragment
    transactions (adding/removing)
    • Limited to full-Fragment animations
    • Support library uses tween animations
    (instead of Animators)

    View Slide

  60. Fragment Animations
    • Fragment.onCreateAnimation()
    • Dynamic tweens
    • FragmentTransaction.setCustomAnimations()
    • Pre-built tweens
    • FragmentTransaction.setTransition() and
    setTransitionStyle()
    • Pre-defined animation styles

    View Slide

  61. Complex Fragment/
    Activity Animations
    • Transition state
    • A --> A + B --> B
    • Invisible Fragments/transparent Activities
    • Single Activity, many Fragments/Views
    • ...Insert your solution here!

    View Slide

  62. View offsets
    • View.offsetLeftAndRight()
    • View.offsetTopAndBottom()
    • Performs well
    • Backwards compatible

    View Slide

  63. set directions
    • View methods: setLeft(),
    setRight(), setTop(),
    setBottom()
    • Skip layout during
    animations
    • Parent layout blows
    away values, may have to
    block

    View Slide

  64. Drawable Animations
    • AnimationDrawable - frame animations
    • Custom animated Drawable in a View
    • Drawable.setCallback()
    • View.verifyDrawable()

    View Slide

  65. layoutAnimation
    • LayoutAnimation
    Controller
    • Staggers animations
    when Views are
    displayed
    • Useful for grid views
    • Useful for widget
    animations

    View Slide

  66. LayoutTransition
    • Automatic animations
    on layout changes
    • Runs when views are
    added/removed

    View Slide

  67. ViewOverlay
    • New in API 4.3
    • Generically add Drawables connected to
    Views
    • Can render outside parent bounds

    View Slide

  68. TransitionManager
    • New in 4.4
    • Transition automatically between two
    ViewGroups
    • Not fully backwards compatible (yet)

    View Slide

  69. Resources
    • Android: goo.gl/4aZIzM
    • DevBytes: goo.gl/QeTM9B
    • Chet Haase: graphics-geek.blogspot.com/
    • Romain Guy: curious-creature.org
    • Google IO Sessions (esp. with Haase/Guy)

    View Slide

  70. Thank You!
    • Blog: http://daniel-codes.blogspot.com/
    • Movies App Source: http://goo.gl/WiRTlQ
    • Twitter: @danlew42
    • Plus: https://plus.google.com/+DanielLew/

    View Slide