Animations

Animations in material design give users feedback on their actions and provide visual continuity as users interact with your app. The material theme provides some default animations for buttons and activity transitions, and the Android L Developer Preview provides additional APIs that let you customize these animations and create new ones:

  • Touch feedback
  • Reveal effect
  • Activity transitions
  • Curved motion
  • View state changes

Touch Feedback

The default touch feedback animations for buttons use the new RippleDrawable class, which transitions between different states with a ripple effect.

In most cases, this functionality should be applied in your view XML by specifying the background as ?android:attr/selectableItemBackground for a bounded ripple or ?android:attr/selectableItemBackgroundBorderless for a ripple that extends beyond the view bounds. You can also create a RippleDrawable and set it as the background of your view. Alternatively, you can define a RippleDrawable as an XML resource using the ripple element. The Android L Developer Preview animates the selection color with a ripple effect.

You can assign a color to RippleDrawable objects. To change the default touch feedback color, use the theme's android:colorControlHighlight attribute.

Reveal Effect

The ViewAnimationUtils.createCircularReveal method enables you to animate a clipping circle to reveal or hide a view.

To reveal a previously invisible view using this effect:

// previously invisible view
View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the final radius for the clipping circle
int finalRadius = myView.getWidth();

// create and start the animator for this view
// (the start radius is zero)
ValueAnimator anim =
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
anim.start();

To hide a previously visible view using this effect:

// previously visible view
final View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();

// create the animation (the final radius is zero)
ValueAnimator anim =
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);

// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        myView.setVisibility(View.INVISIBLE);
    }
});

// start the animation
anim.start();

Activity Transitions

You can specify custom animations for enter and exit transitions and for transitions of shared elements between activities.

  • An enter transition determines how views in an activity enter the scene. For example, in the explode enter transition, the views enter the scene from the outside and fly in towards the center of the screen.
  • An exit transition determines how views in an activity exit the scene. For example, in the explode exit transition, the views exit the scene away from the center.
  • A shared elements transition determines how views that are shared between two activities transition between these activities. For example, if two activities have the same image in different positions and sizes, the moveImage shared element transition translates and scales the image smoothly between these activities.

The Android L Developer Preview supports these enter and exit transitions:

  • explode - Moves views in or out from the center of the scene.
  • slide - Moves views in or out from one of the edges of the scene.
  • fade - Moves views in or out of the scene.

Any transition that extends the android.transition.Visibility class is supported as an enter or exit transition. For more information, see the API reference for the android.transition.Transition class.

The Android L Developer Preview also supports these shared elements transitions:

  • changeBounds - Animates the changes in layout bounds of target views.
  • changeClipBounds - Animates the changes in clip bounds of target views.
  • changeTransform - Animates the changes in scale and rotation of target views.
  • moveImage - Animates changes in size and scale type for an image view.

When you enable activity transitions in your app, the default cross-fading transition is activated between the entering and exiting activities.

  Figure 1 - A scene transition with one shared element.

Specify custom transitions

First, enable window content transitions with the android:windowContentTransitions attribute when you define a style that inherits from the material theme. You can also specify enter, exit, and shared element transitions in your style definition:

<style name="BaseAppTheme" parent="android:Theme.Material">
  <!-- enable window content transitions -->
  <item name="android:windowContentTransitions">true</item>

  <!-- specify enter and exit transitions -->
  <item name="android:windowEnterTransition">@transition/explode</item>
  <item name="android:windowExitTransition">@transition/explode</item>

  <!-- specify shared element transitions -->
  <item name="android:windowSharedElementEnterTransition">
    @transition/move_image</item>
  <item name="android:windowSharedElementExitTransition">
    @transition/move_image</item>
</style>

The move_image transition in this example is defined as follows:

<!-- res/transition/move_image.xml -->
<!-- (see also Shared Transitions below) -->
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
  <moveImage/>
</transitionSet>

The moveImage element corresponds to the android.transition.MoveImage class. For more information, see the API reference for android.transition.Transition.

To enable window content transitions in your code instead, call the Window.requestFeature method:

// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

// set an exit transition
getWindow().setExitTransition(new Explode());

To specify transitions in your code, call these methods with a Transition object:

  • Window.setEnterTransition
  • Window.setExitTransition
  • Window.setSharedElementEnterTransition
  • Window.setSharedElementExitTransition

The setExitTransition and setSharedElementExitTransition methods define the exit transition for the calling activity. The setEnterTransition and setSharedElementEnterTransition methods define the enter transition for the called activity.

To get the full effect of a transition, you must enable window content transitions on both the calling and called activities. Otherwise, the calling activity will start the exit transition, but then you'll see a window transition (like scale or fade).

To start an enter transition as soon as possible, use the Window.setAllowEnterTransitionOverlap method on the called activity. This lets you have more dramatic enter transitions. The same applies for the calling activity and exit transitions with the Window.setAllowExitTransitionOverlap method.

Start an activity using transitions

If you enable transitions and set an exit transition for an activity, the transition is activated when you launch another activity with the startActivity method. If you have set an enter transition for the second activity, the transition is also activated when the activity starts.

Shared elements transitions

To make a screen transition animation between two activities that have a shared element:

  1. Enable window content transitions in your style.
  2. Specify a shared elements transition in your style.
  3. Define your transition as an XML resource.
  4. Assign a common name to the shared elements in both layouts with the android:viewName attribute.
  5. Use the ActivityOptions.makeSceneTransitionAnimation method.
// get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);

// get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);

// define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, Activity2.class);
        // create the transition animation - the images in the layouts
        // of both activities are defined with android:viewName="robot"
        ActivityOptions options = ActivityOptions
            .makeSceneTransitionAnimation(this, androidRobotView, "robot");
        // start the new activity
        startActivity(intent, options.toBundle());
    }
});

For shared dynamic views that you generate in your code, use the View.setViewName method to specify a common element name in both activities.

To reverse the scene transition animation when you finish the second activity, call the Activity.finishAfterTransition method instead of Activity.finish.

Multiple shared elements

To make a scene transition animation between two activities that have more than one shared element, define the shared elements in both layouts with the android:viewName attribute (or use the View.setViewName in both activities), and create an ActivityOptions object as follows:

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(view1, "agreedName1"),
        Pair.create(view2, "agreedName2"));

Curved Motion

Animations in material design rely on curves for time interpolation and spatial movement patterns. The Android L Developer Preview provides new APIs that enable you to define custom timing curves and curved motion patterns for animations.

The PathInterpolator class is a new interpolator based on a Bézier curve or a Path object. This interpolator specifies a motion curve in a 1x1 square, with anchor points at (0,0) and (1,1) and control points as specified using the constructor arguments. You can also define a PathInterpolator as an XML resource:

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.4"
    android:controlY1="0"
    android:controlX2="1"
    android:controlY2="1"/>

The Android L Developer Preview provides XML resources for the three basic curves in the material design specification:

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

You can pass a PathInterpolator object to the Animator.setInterpolation method.

The ObjectAnimator class has new constructors that enable you to animate coordinates along a path using two or more properties at once. For example, the following animator uses a Path object to animate the X and Y properties of a view:

ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();

Animating View State Changes

The new StateListAnimator class lets you define animators that run when the state of a view changes. The following example shows how to define an StateListAnimator as an XML resource:

<!-- animate the translationZ property of a view when pressed -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="100"
        android:valueTo="2"
        android:valueType="floatType"/>
        <!-- you could have other objectAnimator elements
             here for "x" and "y", or other properties -->
    </set>
  </item>
  <item android:state_enabled="true"
    android:state_pressed="false"
    android:state_focused="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="100"
        android:valueTo="2"
        android:valueType="floatType"/>
    </set>
  </item>
</selector>

Note: There is a known issue in the L Developer Preview release that requires valueFrom values to be provided in StateListAnimator animations to get the correct behavior.

The new AnimatedStateListDrawable class lets you create drawables that show animations between state changes of the associated view. Some of the system widgets in the Android L Developer Preview use these animations by default. The following example shows how to define an AnimatedStateListDrawable as an XML resource:

<!-- res/drawable/myanimstatedrawable.xml -->
<animated-selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
        android:state_pressed="true"/>
    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
        android:state_focused="true"/>
    <item android:id="@id/default"
        android:drawable="@drawable/drawableD"/>

    <!-- specify a transition -->
    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
        <animation-list>
            <item android:duration="15" android:drawable="@drawable/dt1"/>
            <item android:duration="15" android:drawable="@drawable/dt2"/>
            ...
        </animation-list>
    </transition>
    ...
</animated-selector>

Drawable Tinting

The Android L Developer Preview enables you to define bitmaps or nine-patches as alpha masks and to tint them using a color resource or a theme attribute that resolves to a color resource (for example, ?android:attr/colorPrimary). You can create these assets only once and color them automatically to match your theme.

To apply a tint to a bitmap, use the setTint method or the android:tint attribute for BitmapDrawable and NinePatchDrawable.

The setTint method also lets you set the Porter-Duff mode used to blend the tint color for NinePatchDrawable and BitmapDrawable objects in your code. To set the tint mode in your layouts, use the android:tintMode attribute.

Extracting Prominent Colors from an Image

The Android L Developer Preview Support Library includes the Palette class, which lets you extract prominent colors from an image. This class extracts the following prominent colors:

  • Vibrant
  • Vibrant dark
  • Vibrant light
  • Muted
  • Muted dark
  • Muted light

To extract these colors, pass a Bitmap object to the Palette.generate static method in the background thread where you load your images. If you can't use that thread, call the Palette.generateAsync method instead and provide a listener.

To retrieve the prominent colors from the image, use the getter methods in the Palette class, such as Palette.getVibrantColor.

For more information, see the API reference for the android.support.v7.graphics.Palette class.