Skip to content

Most visited

Recently visited

navigation

定义定制动画

Material Design 中的动画将为用户提供操作反馈并在用户与您的应用进行互动时提供视觉连续性。 材料主题将为按钮与操作行为转换提供一些默认动画,而 Android 5.0(API 级别 21)及更高版本可让您定制这些动画,同时也可创建新动画:

定制触摸反馈

Material Design 中的触摸反馈可在用户与 UI 元素互动时,在接触点上提供即时视觉确认。 适用于按钮的默认触摸动画使用全新 RippleDrawable 类别,以波纹效果实现不同状态间的转换。

在大多数情况下,您应以下列方式指定视图背景,在您的视图 XML 中应用此功能:

注意:selectableItemBackgroundBorderless 是 API 级别 21 中推出的新属性。

此外,您可利用 ripple 元素将 RippleDrawable 定义为一个 XML 资源。

您可以为 RippleDrawable 对象指定一种颜色。如果要改变默认触摸反馈颜色,请使用主题的 android:colorControlHighlight 属性。

如果要了解更多信息,请参阅 RippleDrawable 类别的 API 参考文档。

使用揭露效果

当您显示或隐藏一组 UI 元素时,揭露动画可为用户提供视觉连续性。ViewAnimationUtils.createCircularReveal() 方法让您能够为裁剪区域添加动画以揭露或隐藏视图。

如果要使用此效果揭露之前不可见的视图:

// 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 = 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();

如果要使用此效果隐藏之前可见的视图:

// 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)
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();

定制操作行为转换

图 1 - 拥有共享元素的转换。

如果要重新播放影片,请点击设备屏幕

Material Design 应用中的操作行为转换透过通用元素之间的移动和转换提供不同状态之间的视觉连接。 您可为进入、退出转换以及操作行为之间的共享元素转换指定定制动画。

Android 5.0(API 级别 21)支持这些进入与退出转换:

任何扩展 Visibility 类别的转换均将获得进入或退出转换支持。 如果要了解更多信息,请参阅 Transition 类别的 API 参考文档。

Android 5.0(API 级别 21)也支持这些共享元素转换:

当您在您的应用中启用操作行为转换,默认的交叉淡入淡出转换将在进入与退出操作行为之间激活。

  图 2 - 拥有一个共享元素的场景转换。

指定定制转换

首先,在定义您从材料主题继承的风格时,使用 android:windowContentTransitions 属性启用窗口内容转换。您也可在您的风格定义中指定进入、退出以及共享元素转换:

<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>

此示例中的 change_image_transform 转换定义如下:

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

changeImageTransform 元素与 ChangeImageTransform 类别相对应。如果要了解更多信息,请参阅 Transition 的 API 参考。

如果要在您的代码中启用窗口内容转换,请调用 Window.requestFeature() 方法:

// 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());

如果要在您的代码中指定转换,请以 Transition 对象调用这些方法:

setExitTransition()setSharedElementExitTransition() 方法定义正在调用的操作行为的退出转换。 setEnterTransition()setSharedElementEnterTransition() 方法定义被调用的操作行为的进入转换。

如果要取得转换的完整效果,您必须在正在调用以及被调用的操作行为上启用窗口内容转换。 否则,正在调用的操作行为将开始退出转换,但是您将会看到窗口转换(例如缩放或淡入淡出)。

如果要尽快开始进入转换,请针对被调用的操作行为使用 Window.setAllowEnterTransitionOverlap() 方法。这可以让您实现更生动的进入转换。

使用转换启动一个操作行为

如果您启用转换并且为一个操作行为设置退出转换,那么在您启动另一个操作行为时,转换将以下列方式激活:

startActivity(intent,
              ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

如果您已为第二个操作行为设置进入转换,则转换也将会在操作行为启动时激活。 如果要在您启动另一个操作行为时禁用转换,请提供 null 选项包。

以共享元素启动一个操作行为

如果要在两个拥有共享元素的操作行为之间安排屏幕转换动画:

  1. 请在您的主题中启用窗口内容转换。
  2. 在您的风格中指定一个共享元素转换。
  3. 将您的转换定义为 XML 资源。
  4. 利用 android:transitionName 属性对两个布局中的共享元素指定一个通用名称。
  5. 使用 ActivityOptions.makeSceneTransitionAnimation() 方法。
// 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());
    }
});

对于在您的代码中生成的共享动态视图,请使用 View.setTransitionName() 方法在两个操作行为中指定一个通用元素名称。

如果要在完成第二项操作行为时反转场景转换动画,请调用 Activity.finishAfterTransition() 方法而非 Activity.finish()

以多个共享元素启动一个操作行为

如果要在两个拥有多个共享元素的操作行为之间安排场景转换动画,请以 android:transitionName 属性(或在两个操作行为中使用 View.setTransitionName() 方法)定义共享元素,并以下列方式创建一个 ActivityOptions 对象:

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

使用曲线运动

Material Design 中的动画利用曲线实现时间内插与空间移动模式。 利用 Android 5.0(API 级别 21)及更高版本,您可为动画定义定制时间曲线以及曲线运动模式。

PathInterpolator 类别是一个基于贝塞尔曲线或 Path 对象的全新插入器。 此插入器在一个 1x1 的正方形内指定一个运动曲线,定位点位于 (0,0) 以及 (1,1),而控制点则使用构造函数参数指定。 您也可以将路径插入器定义为一个 XML 资源:

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

系统将为 Material Design 规范中的三种基本曲线提供 XML 资源:

您可以将一个 PathInterpolator 对象传递给 Animator.setInterpolator() 方法。

ObjectAnimator 类别拥有新的构造函数,可让您一次使用两个或更多属性在路径上为坐标添加动画。 例如,下列动画使用 Path 对象为视图的 X 和 Y 属性添加动画:

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

为视图状态改变添加动画

StateListAnimator 类别让您能够定义视图状态改变时运行的动画。 下列示例显示如何将 StateListAnimator 定义为一个 XML 资源:

<!-- 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>

如果要将定制视图状态动画附加至一个视图,请依照此示例使用 XML 资源文件中的 selector 元素定义一个动画,并使用 android:stateListAnimator 属性将此动画分配给您的视图。 如果要将一个状态列表动画分配给您的代码内的一个视图,请使用 AnimationInflater.loadStateListAnimator() 方法,并以 View.setStateListAnimator() 方法将动画分配给您的视图。

当您的主题扩展材料主题时,在默认情况下按钮将拥有一个 Z 动画。如果要避免您的按钮出现这类行为,请将 android:stateListAnimator 属性设置为 @null

AnimatedStateListDrawable 类别让您能够创建图片,显示相关视图之间的状态变化。 Android 5.0 中的某些系统小组件在默认情况下使用这些动画。 下列示例显示如何将 AnimatedStateListDrawable 定义为一个 XML 资源:

<!-- 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>

为矢量图片添加动画

矢量图片可在不丢失定义的情况下缩放。 AnimatedVectorDrawable 类别可让您为矢量图片的属性添加动画。

您通常可以在 3 个 XML 文件中定义添加动画的矢量图片:

添加动画的矢量图片可为 <group> 以及 <path> 元素的属性添加动画。<group> 元素定义路径集或子组,而 <path> 元素则定义将绘制的路径。

当您定义一个您想要添加动画的矢量图片时,请使用 android:name 属性给这些群组和路径指定一个唯一名称,以便让您能够从您的动画定义中引用这些群组或路径。 例如:

<!-- 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
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="v"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>

已添加动画的矢量图片定义按名称引用矢量图片内的群组和路径:

<!-- 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>

动画定义代表着 ObjectAnimatorAnimatorSet 对象。此示例中的第一个动画将目标群组旋转 360 度:

<!-- res/anim/rotation.xml -->
<objectAnimator
    android:duration="6000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360" />

此示例中的第二个动画对矢量图片的路径进行变形。 两个路径均需可兼容变形操作:两个路径均需拥有相同数量的指令,而且每个指令均需拥有相同数量的参数。

<!-- 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>

如果要了解更多信息,请参阅 AnimatedVectorDrawable 的 API 参考文档。

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)