| page.title=Defining Custom Animations |
| |
| @jd:body |
| |
| <div id="tb-wrapper"> |
| <div id="tb"> |
| <h2>This lesson teaches you to</h2> |
| <ol> |
| <li><a href="#Touch">Customize Touch Feedback</a></li> |
| <li><a href="#Reveal">Use the Reveal Effect</a></li> |
| <li><a href="#Transitions">Customize Activity Transitions</a></li> |
| <li><a href="#ViewState">Animate View State Changes</a></li> |
| <li><a href="#AnimVector">Animate Vector Drawables</a></li> |
| </ol> |
| <h2>You should also read</h2> |
| <ul> |
| <li><a href="http://www.google.com/design/spec">Material design specification</a></li> |
| <li><a href="{@docRoot}design/material/index.html">Material design on Android</a></li> |
| </ul> |
| </div> |
| </div> |
| |
| |
| <p>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 Android 5.0 (API level 21) and above lets you customize |
| these animations and create new ones:</p> |
| |
| <ul> |
| <li>Touch feedback</li> |
| <li>Circular Reveal</li> |
| <li>Activity transitions</li> |
| <li>Curved motion</li> |
| <li>View state changes</li> |
| </ul> |
| |
| |
| <h2 id="Touch">Customize Touch Feedback</h2> |
| |
| <p>Touch feedback in material design provides an instantaneous visual confirmation at the |
| point of contact when users interact with UI elements. The default touch feedback animations |
| for buttons use the new {@link android.graphics.drawable.RippleDrawable} class, which transitions |
| between different states with a ripple effect.</p> |
| |
| <p>In most cases, you should apply this functionality in your view XML by specifying the view |
| background as:</p> |
| |
| <ul> |
| <li><code>?android:attr/selectableItemBackground</code> for a bounded ripple.</li> |
| <li><code>?android:attr/selectableItemBackgroundBorderless</code> for a ripple that extends beyond |
| the view. It will be drawn upon, and bounded by, the nearest parent of the view with a non-null |
| background.</li> |
| </ul> |
| |
| <p class="note"><strong>Note:</strong> <code>selectableItemBackgroundBorderless</code> is a new |
| attribute introduced in API level 21.</p> |
| |
| |
| <p>Alternatively, you can define a {@link android.graphics.drawable.RippleDrawable} |
| as an XML resource using the <code>ripple</code> element.</p> |
| |
| <p>You can assign a color to {@link android.graphics.drawable.RippleDrawable} objects. To change |
| the default touch feedback color, use the theme's <code>android:colorControlHighlight</code> |
| attribute.</p> |
| |
| <p>For more information, see the API reference for the {@link |
| android.graphics.drawable.RippleDrawable} class.</p> |
| |
| |
| <h2 id="Reveal">Use the Reveal Effect</h2> |
| |
| <p>Reveal animations provide users visual continuity when you show or hide a group of UI |
| elements. The {@link android.view.ViewAnimationUtils#createCircularReveal |
| ViewAnimationUtils.createCircularReveal()} method enables you to animate a clipping circle to |
| reveal or hide a view.</p> |
| |
| <p>To reveal a previously invisible view using this effect:</p> |
| |
| <pre> |
| // previously invisible view |
| View myView = findViewById(R.id.my_view); |
| |
| // get the center for the clipping circle |
| int cx = myView.getWidth() / 2; |
| int cy = myView.getHeight() / 2; |
| |
| // get the final radius for the clipping circle |
| int finalRadius = Math.max(myView.getWidth(), myView.getHeight()); |
| |
| // create the animator for this view (the start radius is zero) |
| Animator anim = |
| ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); |
| |
| // make the view visible and start the animation |
| myView.setVisibility(View.VISIBLE); |
| anim.start(); |
| </pre> |
| |
| <p>To hide a previously visible view using this effect:</p> |
| |
| <pre> |
| // previously visible view |
| final View myView = findViewById(R.id.my_view); |
| |
| // get the center for the clipping circle |
| int cx = myView.getWidth() / 2; |
| int cy = myView.getHeight() / 2; |
| |
| // get the initial radius for the clipping circle |
| int initialRadius = myView.getWidth(); |
| |
| // create the animation (the final radius is zero) |
| Animator 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(); |
| </pre> |
| |
| |
| <h2 id="Transitions">Customize Activity Transitions</h2> |
| |
| <!-- shared transition video --> |
| <div style="width:290px;margin-left:35px;float:right"> |
| <div class="framed-nexus5-port-span-5"> |
| <video class="play-on-hover" autoplay=""> |
| <source src="{@docRoot}design/material/videos/ContactsAnim.mp4"> |
| <source src="{@docRoot}design/material/videos/ContactsAnim.webm"> |
| <source src="{@docRoot}design/material/videos/ContactsAnim.ogv"> |
| </video> |
| </div> |
| <div style="font-size:10pt;margin-left:20px;margin-bottom:30px"> |
| <p class="img-caption" style="margin-top:3px;margin-bottom:10px"><strong>Figure 1</strong> - A |
| transition with shared elements.</p> |
| <em>To replay the movie, click on the device screen</em> |
| </div> |
| </div> |
| |
| <p>Activity transitions in material design apps provide visual connections between different states |
| through motion and transformations between common elements. You can specify custom animations for |
| enter and exit transitions and for transitions of shared elements between activities.</p> |
| |
| <ul> |
| <li>An <strong>enter</strong> transition determines how views in an activity enter the scene. |
| For example, in the <em>explode</em> enter transition, the views enter the scene from the outside |
| and fly in towards the center of the screen.</li> |
| |
| <li>An <strong>exit</strong> transition determines how views in an activity exit the scene. For |
| example, in the <em>explode</em> exit transition, the views exit the scene away from the |
| center.</li> |
| |
| <li>A <strong>shared elements</strong> 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 <em>changeImageTransform</em> shared element transition |
| translates and scales the image smoothly between these activities.</li> |
| </ul> |
| |
| <p>Android 5.0 (API level 21) supports these enter and exit transitions:</p> |
| |
| <ul> |
| <li><em>explode</em> - Moves views in or out from the center of the scene.</li> |
| <li><em>slide</em> - Moves views in or out from one of the edges of the scene.</li> |
| <li><em>fade</em> - Adds or removes a view from the scene by changing its opacity.</li> |
| </ul> |
| |
| <p>Any transition that extends the {@link android.transition.Visibility} class is supported |
| as an enter or exit transition. For more information, see the API reference for the |
| {@link android.transition.Transition} class.</p> |
| |
| <p>Android 5.0 (API level 21) also supports these shared elements transitions:</p> |
| |
| <ul> |
| <li><em>changeBounds</em> - Animates the changes in layout bounds of target views.</li> |
| <li><em>changeClipBounds</em> - Animates the changes in clip bounds of target views.</li> |
| <li><em>changeTransform</em> - Animates the changes in scale and rotation of target views.</li> |
| <li><em>changeImageTransform</em> - Animates changes in size and scale of target images.</li> |
| </ul> |
| |
| <p>When you enable activity transitions in your app, the default cross-fading transition is |
| activated between the entering and exiting activities.</p> |
| |
| <img src="{@docRoot}training/material/images/SceneTransition.png" alt="" width="600" height="405" |
| style="margin-top:20px"/> |
| <p class="img-caption"> |
| <strong>Figure 2</strong> - A scene transition with one shared element. |
| </p> |
| |
| <h3>Specify custom transitions</h3> |
| |
| <p>First, enable window content transitions with the <code>android:windowContentTransitions</code> |
| 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:</p> |
| |
| <pre> |
| <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/change_image_transform</item> |
| <item name="android:windowSharedElementExitTransition"> |
| @transition/change_image_transform</item> |
| </style> |
| </pre> |
| |
| <p>The <code>change_image_transform</code> transition in this example is defined as follows:</p> |
| |
| <pre> |
| <!-- res/transition/change_image_transform.xml --> |
| <!-- (see also Shared Transitions below) --> |
| <transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> |
| <changeImageTransform/> |
| </transitionSet> |
| </pre> |
| |
| <p>The <code>changeImageTransform</code> element corresponds to the |
| {@link android.transition.ChangeImageTransform} class. For more information, see the API |
| reference for {@link android.transition.Transition}.</p> |
| |
| <p>To enable window content transitions in your code instead, call the |
| {@link android.view.Window#requestFeature Window.requestFeature()} method:</p> |
| |
| <pre> |
| // 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()); |
| </pre> |
| |
| <p>To specify transitions in your code, call these methods with a {@link |
| android.transition.Transition} object:</p> |
| |
| <ul> |
| <li>{@link android.view.Window#setEnterTransition Window.setEnterTransition()}</li> |
| <li>{@link android.view.Window#setExitTransition Window.setExitTransition()}</li> |
| <li>{@link android.view.Window#setSharedElementEnterTransition |
| Window.setSharedElementEnterTransition()}</li> |
| <li>{@link android.view.Window#setSharedElementExitTransition |
| Window.setSharedElementExitTransition()}</li> |
| </ul> |
| |
| <p>The {@link android.view.Window#setExitTransition setExitTransition()} and {@link |
| android.view.Window#setSharedElementExitTransition setSharedElementExitTransition()} methods define |
| the exit transition for the calling activity. The {@link android.view.Window#setEnterTransition |
| setEnterTransition()} and {@link android.view.Window#setSharedElementEnterTransition |
| setSharedElementEnterTransition()} methods define the enter transition for the called activity.</p> |
| |
| <p>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).</p> |
| |
| <p>To start an enter transition as soon as possible, use the |
| {@link android.view.Window#setAllowEnterTransitionOverlap Window.setAllowEnterTransitionOverlap()} |
| method on the called activity. This lets you have more dramatic enter transitions.</p> |
| |
| <h3>Start an activity using transitions</h3> |
| |
| <p>If you enable transitions and set an exit transition for an activity, the transition is activated |
| when you launch another activity as follows:</p> |
| |
| <pre> |
| startActivity(intent, |
| ActivityOptions.makeSceneTransitionAnimation(this).toBundle()); |
| </pre> |
| |
| <p>If you have set an enter transition for the second activity, the transition is also activated |
| when the activity starts. To disable transitions when you start another activity, provide |
| a <code>null</code> options bundle.</p> |
| |
| <h3>Start an activity with a shared element</h3> |
| |
| <p>To make a screen transition animation between two activities that have a shared element:</p> |
| |
| <ol> |
| <li>Enable window content transitions in your theme.</li> |
| <li>Specify a shared elements transition in your style.</li> |
| <li>Define your transition as an XML resource.</li> |
| <li>Assign a common name to the shared elements in both layouts with the |
| <code>android:transitionName</code> attribute.</li> |
| <li>Use the {@link android.app.ActivityOptions#makeSceneTransitionAnimation |
| ActivityOptions.makeSceneTransitionAnimation()} method.</li> |
| </ol> |
| |
| <pre> |
| // 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:transitionName="robot" |
| ActivityOptions options = ActivityOptions |
| .makeSceneTransitionAnimation(this, androidRobotView, "robot"); |
| // start the new activity |
| startActivity(intent, options.toBundle()); |
| } |
| }); |
| </pre> |
| |
| <p>For shared dynamic views that you generate in your code, use the |
| {@link android.view.View#setTransitionName View.setTransitionName()} method to specify a common |
| element name in both activities.</p> |
| |
| <p>To reverse the scene transition animation when you finish the second activity, call the |
| {@link android.app.Activity#finishAfterTransition Activity.finishAfterTransition()} |
| method instead of {@link android.app.Activity#finish Activity.finish()}.</p> |
| |
| <h3>Start an activity with multiple shared elements</h3> |
| |
| <p>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 <code>android:transitionName</code> |
| attribute (or use the {@link android.view.View#setTransitionName View.setTransitionName()} method |
| in both activities), and create an {@link android.app.ActivityOptions} object as follows:</p> |
| |
| <pre> |
| ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, |
| Pair.create(view1, "agreedName1"), |
| Pair.create(view2, "agreedName2")); |
| </pre> |
| |
| |
| <h2 id="CurvedMotion">Use Curved Motion</h2> |
| |
| <p>Animations in material design rely on curves for time interpolation and spatial movement |
| patterns. With Android 5.0 (API level 21) and above, you can define custom timing curves and |
| curved motion patterns for animations.</p> |
| |
| <p>The {@link android.view.animation.PathInterpolator} class is a new interpolator based on a |
| Bézier curve or a {@link android.graphics.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 path interpolator as an XML resource:</p> |
| |
| <pre> |
| <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" |
| android:controlX1="0.4" |
| android:controlY1="0" |
| android:controlX2="1" |
| android:controlY2="1"/> |
| </pre> |
| |
| <p>The system provides XML resources for the three basic curves in the material design |
| specification:</p> |
| |
| <ul> |
| <li><code>@interpolator/fast_out_linear_in.xml</code></li> |
| <li><code>@interpolator/fast_out_slow_in.xml</code></li> |
| <li><code>@interpolator/linear_out_slow_in.xml</code></li> |
| </ul> |
| |
| <p>You can pass a {@link android.view.animation.PathInterpolator} object to the {@link |
| android.animation.Animator#setInterpolator Animator.setInterpolator()} method.</p> |
| |
| <p>The {@link android.animation.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 {@link android.graphics.Path} object to animate the X and Y properties of a view:</p> |
| |
| <pre> |
| ObjectAnimator mAnimator; |
| mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); |
| ... |
| mAnimator.start(); |
| </pre> |
| |
| |
| <h2 id="ViewState">Animate View State Changes</h2> |
| |
| <p>The {@link android.animation.StateListAnimator} class lets you define animators that run when |
| the state of a view changes. The following example shows how to define an {@link |
| android.animation.StateListAnimator} as an XML resource:</p> |
| |
| <pre> |
| <!-- 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="@android:integer/config_shortAnimTime" |
| android:valueTo="2dp" |
| 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="0" |
| android:valueType="floatType"/> |
| </set> |
| </item> |
| </selector> |
| </pre> |
| |
| <p>To attach custom view state animations to a view, define an animator using the |
| <code>selector</code> element in an XML resource file as in this example, and assign it to your |
| view with the <code>android:stateListAnimator</code> attribute. To assign a state list animator |
| to a view in your code, use the {@link android.animation.AnimatorInflater#loadStateListAnimator |
| AnimationInflater.loadStateListAnimator()} method, and assign the animator to your view with the |
| {@link android.view.View#setStateListAnimator View.setStateListAnimator()} method.</p> |
| |
| <p>When your theme extends the material theme, buttons have a Z animation by default. To avoid this |
| behavior in your buttons, set the <code>android:stateListAnimator</code> attribute to |
| <code>@null</code>.</p> |
| |
| <p>The {@link android.graphics.drawable.AnimatedStateListDrawable} class lets you create drawables |
| that show animations between state changes of the associated view. Some of the system widgets in |
| Android 5.0 use these animations by default. The following example shows how |
| to define an {@link android.graphics.drawable.AnimatedStateListDrawable} as an XML resource:</p> |
| |
| <pre> |
| <!-- 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> |
| </pre> |
| |
| |
| <h2 id="AnimVector">Animate Vector Drawables</h2> |
| |
| <p><a href="{@docRoot}training/material/drawables.html#VectorDrawables">Vector Drawables</a> are |
| scalable without losing definition. The {@link android.graphics.drawable.AnimatedVectorDrawable} |
| class lets you animate the properties of a vector drawable.</p> |
| |
| <p>You normally define animated vector drawables in three XML files:</p> |
| |
| <ul> |
| <li>A vector drawable with the <code><vector></code> element in |
| <code>res/drawable/</code></li> |
| <li>An animated vector drawable with the <code><animated-vector></code> element in |
| <code>res/drawable/</code></li> |
| <li>One or more object animators with the <code><objectAnimator></code> element in |
| <code>res/anim/</code></li> |
| </ul> |
| |
| <p>Animated vector drawables can animate the attributes of the <code><group></code> and |
| <code><path></code> elements. The <code><group></code> elements defines a set of |
| paths or subgroups, and the <code><path></code> element defines paths to be drawn.</p> |
| |
| <p>When you define a vector drawable that you want to animate, use the <code>android:name</code> |
| attribute to assign a unique name to groups and paths, so you can refer to them from your animator |
| definitions. For example:</p> |
| |
| <pre> |
| <!-- res/drawable/vectordrawable.xml --> |
| <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| android:height="64dp" |
| android:width="64dp" |
| android:viewportHeight="600" |
| android:viewportWidth="600"> |
| <group |
| <strong>android:name="rotationGroup"</strong> |
| android:pivotX="300.0" |
| android:pivotY="300.0" |
| android:rotation="45.0" > |
| <path |
| <strong>android:name="v"</strong> |
| android:fillColor="#000000" |
| android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> |
| </group> |
| </vector> |
| </pre> |
| |
| <p>The animated vector drawable definition refers to the groups and paths in the vector drawable |
| by their names:</p> |
| |
| <pre> |
| <!-- res/drawable/animvectordrawable.xml --> |
| <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" |
| android:drawable="@drawable/vectordrawable" > |
| <target |
| android:name="rotationGroup" |
| android:animation="@anim/rotation" /> |
| <target |
| android:name="v" |
| android:animation="@anim/path_morph" /> |
| </animated-vector> |
| </pre> |
| |
| <p>The animation definitions represent {@link android.animation.ObjectAnimator} or {@link |
| android.animation.AnimatorSet} objects. The first animator in this example rotates the target |
| group 360 degrees:</p> |
| |
| <pre> |
| <!-- res/anim/rotation.xml --> |
| <objectAnimator |
| android:duration="6000" |
| android:propertyName="rotation" |
| android:valueFrom="0" |
| android:valueTo="360" /> |
| </pre> |
| |
| <p>The second animator in this example morphs the vector drawable's path from one shape to |
| another. Both paths must be compatible for morphing: they must have the same number of commands |
| and the same number of parameters for each command.</p> |
| |
| <pre> |
| <!-- res/anim/path_morph.xml --> |
| <set xmlns:android="http://schemas.android.com/apk/res/android"> |
| <objectAnimator |
| android:duration="3000" |
| android:propertyName="pathData" |
| android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" |
| android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" |
| android:valueType="pathType" /> |
| </set> |
| </pre> |
| |
| <p>For more information, see the API reference for {@link |
| android.graphics.drawable.AnimatedVectorDrawable}.</p> |