使用动画启动 activity

Material Design 应用中的 activity 过渡提供了 通过常见元素之间的运动和转换形成不同的状态。 您可以为进入和退出过渡以及 共享元素的转换。

图 1. 答 具有共享元素的过渡。

  • 进入过渡决定了 Activity 中的视图 进入场景。例如,在 explode Enter 转换中, 视图从外面进入场景,飞向内景的中心, 屏幕。
  • 退出过渡决定了 Activity 退出中的视图 场景。例如,在 explode 退出过渡中,视图 让镜头离开场景中心
  • 共享元素过渡决定了 两个 activity 之间共享的转换会在这两个 activity 之间实现。例如: 如果两个 activity 使用相同的图片,但位置和尺寸不同, changeImageTransform 共享元素过渡 在这些活动之间平滑地缩放图片。

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

  • explode:将视图移入或移出场景中心。
  • slide:将视图从 场景。
  • fade:通过更改其视图名称在场景中添加或移除视图 不透明度。

系统支持将任何扩展 Visibility 类的过渡作为进入或退出过渡。 有关详情,请参阅 Transition 类。

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

  • changeBounds:为目标布局边界的变化添加动画效果 观看次数。
  • changeClipBounds:以动画方式呈现目标裁剪边界的变化 观看次数。
  • changeTransform:为元素的缩放和旋转变化添加动画效果 目标视图。
  • changeImageTransform:为大小和缩放比例的变化添加动画效果 目标图片。

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

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

如需查看为使用共享元素的 activity 添加动画效果的示例代码,请参阅 ActivitySceneTransitionBasic 模式。

检查系统版本

Activity 过渡 API 适用于 Android 5.0 (API 21) 及更高版本。要保持与早期版本的 Android 兼容,请检查 系统version 调用以下任一功能的 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
}

指定自定义过渡

首先,使用 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 类。如需了解详情,请参阅 API Transition 的参考资料。

要改为在代码中启用窗口内容转换,请调用 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() 函数定义退出 为正在调用的 activity 提供过渡。setEnterTransition()setSharedElementEnterTransition() 函数用于定义输入 为被调用的 activity 提供此属性。

若要获得完整的转场效果,您必须启用窗口内容 转换。否则,调用 activity 启动退出转换,但是随后你会看到窗口 例如缩放或淡出等

要尽快开始进入过渡,请使用 Window.setAllowEnterTransitionOverlap() 函数。这样一来,您的进入过渡效果会更加精彩。

启动使用过渡的 Activity

如果您启用转换并为操作行为设置退出转换, 转换会在您启动另一个 activity 时激活,如下所示:

Kotlin

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

Java

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

如果您为第二个 activity 设置了进入转场,该转场效果也会 在 Activity 启动时激活。开始播放时停用转场效果 另一个 activity,请提供 null 选项包。

启动具有一个共享元素的 Activity

要在两个具有不同颜色的 activity 之间添加屏幕过渡动画,请执行以下操作: 共享元素,请执行以下操作:

  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 时反转场景转换动画,请调用 Activity.finishAfterTransition() 函数,而不是 Activity.finish()

启动具有多个共享元素的 Activity

在两个活动数量较多的 activity 之间添加场景过渡动画 定义两个布局中的共享元素,并使用 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"));