Material Design 应用中的 Activity 过渡通过运动和常见元素之间的转换在不同状态之间提供视觉连接。您可以为进入和退出过渡以及 Activity 之间共享元素的过渡指定自定义动画。
- 进入过渡决定 Activity 中的视图如何进入场景。例如,在
explode
进入过渡中,视图从外部进入场景并向内飞到屏幕中心。 - 退出过渡决定 Activity 中的视图如何退出场景。例如,在
explode
退出过渡中,视图从中心退出场景。 - 共享元素过渡决定两个 Activity 之间共享的视图如何在这些 Activity 之间过渡。例如,如果两个 Activity 在不同位置和大小上具有相同的图像,则
changeImageTransform
共享元素过渡会在这些 Activity 之间平滑地转换和缩放图像。
Android 支持以下进入和退出过渡
explode
:将视图移入或移出场景中心。slide
:将视图移入或移出场景的边缘之一。fade
:通过更改视图的不透明度将其添加到场景中或从场景中移除。
任何扩展Visibility
类的过渡都支持作为进入或退出过渡。有关更多信息,请参阅Transition
类的 API 参考。
Android 还支持以下共享元素过渡
changeBounds
:动画化目标视图的布局边界变化。changeClipBounds
:动画化目标视图的剪辑边界变化。changeTransform
:动画化目标视图的缩放和旋转变化。changeImageTransform
:动画化目标图像的大小和缩放变化。
在应用中启用 Activity 过渡时,进入和退出 Activity 之间会激活默认的交叉淡入淡出过渡。
有关使用共享元素在 Activity 之间进行动画的示例代码,请参阅ActivitySceneTransitionBasic。
检查系统版本
Activity 过渡 API 在 Android 5.0(API 21)及更高版本上可用。为了保持与早期 Android 版本的兼容性,在调用任何这些功能的 API 之前,请在运行时检查系统版本
Kotlin
// Check if we're running on Android 5.0 or higher if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Apply activity transition } else { // Swap without transition }
Java
// Check if we're running on Android 5.0 or higher if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Apply activity transition } else { // Swap without transition }
指定自定义过渡
首先,在定义继承自 Material 主题的样式时,使用android:windowActivityTransitions
属性启用窗口内容过渡。您也可以在样式定义中指定进入、退出和共享元素过渡
<style name="BaseAppTheme" parent="android:Theme.Material"> <!-- enable window content transitions --> <item name="android:windowActivityTransitions">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()
函数
Kotlin
// Inside your activity (if you did not enable transitions in your theme) with(window) { requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) // Set an exit transition exitTransition = Explode() }
Java
// Inside your activity (if you did not enable transitions in your theme) getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS); // Set an exit transition getWindow().setExitTransition(new Explode());
要在代码中指定过渡,请使用Transition
对象调用以下函数
Window.setEnterTransition()
Window.setExitTransition()
Window.setSharedElementEnterTransition()
Window.setSharedElementExitTransition()
setExitTransition()
和setSharedElementExitTransition()
函数定义调用 Activity 的退出过渡。setEnterTransition()
和setSharedElementEnterTransition()
函数定义被调用 Activity 的进入过渡。
要获得过渡的全部效果,必须在调用和被调用 Activity 上都启用窗口内容过渡。否则,调用 Activity 会启动退出过渡,但随后您会看到窗口过渡(如缩放或淡入淡出)。
要尽快启动进入过渡,请在被调用 Activity 上使用Window.setAllowEnterTransitionOverlap()
函数。这使您可以拥有更引人注目的进入过渡。
使用过渡启动 Activity
如果启用过渡并为 Activity 设置退出过渡,则在您启动另一个 Activity 时会激活过渡,如下所示
Kotlin
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle())
Java
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
如果为第二个 Activity 设置了进入过渡,则该过渡在 Activity 启动时也会激活。要在启动另一个 Activity 时禁用过渡,请提供一个null
选项包。
使用共享元素启动 Activity
要使具有共享元素的两个 Activity 之间进行屏幕过渡动画,请执行以下操作
- 在您的主题中启用窗口内容过渡。
- 在您的样式中指定共享元素过渡。
- 将您的过渡定义为 XML 资源。
- 使用
android:transitionName
属性在两个布局中为共享元素分配一个通用名称。 - 使用
ActivityOptions.makeSceneTransitionAnimation()
函数。
Kotlin
// Get the element that receives the click event val imgContainerView = findViewById<View>(R.id.img_container) // Get the common element for the transition in this activity val androidRobotView = findViewById<View>(R.id.image_small) // Define a click listener imgContainerView.setOnClickListener( { val intent = Intent(this, Activity2::class.java) // Create the transition animation - the images in the layouts // of both activities are defined with android:transitionName="robot" val options = ActivityOptions .makeSceneTransitionAnimation(this, androidRobotView, "robot") // Start the new activity startActivity(intent, options.toBundle()) })
Java
// 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 中指定一个通用元素名称。
要在完成第二个 Activity 时反转场景过渡动画,请调用Activity.finishAfterTransition()
函数,而不是Activity.finish()
。
使用多个共享元素启动 Activity
要使具有多个共享元素的两个 Activity 之间进行场景过渡动画,请使用android:transitionName
属性在两个布局中定义共享元素(或在两个 Activity 中使用View.setTransitionName()
函数),并如下创建ActivityOptions
对象
Kotlin
// Rename the Pair class from the Android framework to avoid a name clash import android.util.Pair as UtilPair ... val options = ActivityOptions.makeSceneTransitionAnimation(this, UtilPair.create(view1, "agreedName1"), UtilPair.create(view2, "agreedName2"))
Java
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2"));