使用动画启动活动

Material Design 应用中的活动过渡通过运动和常用元素之间的转换在不同状态之间提供视觉连接。您可以为进入和退出过渡以及活动之间共享元素的过渡指定自定义动画。

图 1. 共享元素的过渡。

  • 进入过渡决定活动中的视图如何进入场景。例如,在explode进入过渡中,视图从外部进入场景,并向内飞到屏幕中心。
  • 退出过渡决定活动中的视图如何退出场景。例如,在explode退出过渡中,视图从中心退出场景。
  • 共享元素过渡决定两个活动之间共享的视图如何在这些活动之间过渡。例如,如果两个活动在不同位置和大小上具有相同的图像,则changeImageTransform共享元素过渡会在这些活动之间平滑地平移和缩放图像。

Android 支持以下进入和退出过渡

  • explode:将视图移向或移出场景中心。
  • slide:将视图从场景的其中一个边缘移入或移出。
  • fade:通过更改视图的不透明度将其添加到场景或从场景中移除。

任何扩展Visibility类的过渡都支持作为进入或退出过渡。有关更多信息,请参阅Transition类的 API 参考。

Android 还支持以下共享元素过渡

  • changeBounds:为目标视图的布局边界变化设置动画。
  • changeClipBounds:为目标视图的剪辑边界变化设置动画。
  • changeTransform:为目标视图的缩放和旋转变化设置动画。
  • changeImageTransform:为目标图像的大小和缩放变化设置动画。

在应用中启用活动过渡时,进入和退出活动之间会激活默认的交叉淡入淡出过渡。

图 2. 带有一个共享元素的场景过渡。

有关使用共享元素在活动之间设置动画的示例代码,请参阅ActivitySceneTransitionBasic

检查系统版本

活动过渡 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对象调用这些函数

函数setExitTransition()setSharedElementExitTransition()定义调用活动的退出过渡。函数setEnterTransition()setSharedElementEnterTransition()定义被调用活动的进入过渡。

要获得过渡的完整效果,必须在调用活动和被调用活动上都启用窗口内容过渡。否则,调用活动会启动退出过渡,但随后您会看到窗口过渡(如缩放或淡入淡出)。

要尽快启动进入过渡,请在被调用活动上使用函数Window.setAllowEnterTransitionOverlap()。这可以让您拥有更戏剧性的进入过渡。

使用过渡启动活动

如果启用了过渡并为活动设置了退出过渡,则在启动另一个活动时会激活该过渡,如下所示

Kotlin

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

Java

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

如果为第二个活动设置了进入过渡,则该过渡在活动启动时也会激活。要在启动另一个活动时禁用过渡,请提供一个null选项捆绑包。

使用共享元素启动活动

要创建具有共享元素的两个活动之间的屏幕过渡动画,请执行以下操作

  1. 在您的主题中启用窗口内容过渡。
  2. 在您的样式中指定共享元素过渡。
  3. 将您的过渡定义为 XML 资源。
  4. 使用属性android:transitionName在两个布局中为共享元素分配一个通用名称。
  5. 使用函数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.finishAfterTransition()而不是Activity.finish()

使用多个共享元素启动活动

要创建具有多个共享元素的两个活动之间的场景过渡动画,请使用属性android:transitionName在两个布局中定义共享元素,或者在两个活动中使用函数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"));