Transition动画效果诞生于Android 4.4,主要负责:

  1. 捕捉在开始场景和结束场景中每个 View 的状态。
  2. 根据视图一个场景移动到另一个场景的差异创建一个 Animator。

应用场景包括:

  • 可以在activity之间跳转的时候添加动画
  • 动画共享元素之间的转换活动
  • activity中布局元素的过渡动画

我们以前实现Activity切换过程的动画的姿势是这样的:

  1. xml设置
    首先我们需要在 AndroidManifest.xml 清单文件中 application 节点使用的theme主题添加属性:
    <item name="android:windowAnimationStyle">@style/AnimationActivity</item>AnimationActivity的属性如下:
<!--Activity进入、退出动画-->
<style name="AnimationActivity" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/in_from_right</item>
<item name="android:activityOpenExitAnimation">@anim/in_from_right_abit</item>
<item name="android:activityCloseEnterAnimation">@anim/out_to_right_abit</item>
<item name="android:activityCloseExitAnimation">@anim/out_to_right</item>
</style>

然后在res/anim中创建对应的文件即可。

  1. 代码设置
    通过在Activity中重写 overridePendingTransition 给当前界面添加进入、退出动画,具体自行搜索,因为这篇博客的重点是在 Transition Animation 上。

进入主题 首先有三种自带的Transition Animation效果

  • fade
  • slide
  • explode

其次生成的方式有2种:

  1. xml生成
    res 下创建 transition资源文件夹,在该文件夹中创建xml文件,比如:
    slide.xml
<?xml version="1.0" encoding="utf-8"?>
<slide xmlns:android="http://schemas.android.com/apk/res/"
  android:duration="500"/>
  1. 代码生成
android.transition.Slide slide = new android.transition.Slide();
//动画时长
slide.setDuration(500);
//动画从哪个方向执行
slide.setSlideEdge(Gravity.TOP);
//动画的状态:MODE_OUT:退出、MODE_IN:进入
slide.setMode(Visibility.MODE_OUT);

使用Transition Animation的姿势如下:

  1. AndroidManifest.xml 清单文件中 application 节点使用的theme主题添加属性(这种方法是在整个app中使用)
<!--转场动画-->
<!--启用窗口内容转换-->
<item name="android:windowContentTransitions">true</item>
<!-- 启用Transition框架,但没有默认的动画, 需要通过bundle设定动画,设定false则从ContentTransition中关闭此效果-->
<item name="android:windowActivityTransitions">true</item>
<!--是否允许动画重叠-->
<item name="android:windowAllowEnterTransitionOverlap">false</item>
<item name="android:windowAllowReturnTransitionOverlap">false</item>

在指定的Activity中使用

在Activity重写的onCreate方法中,在super.onCreate(savedInstanceState);之前添加如下代码:

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
getWindow().setAllowEnterTransitionOverlap(false);
getWindow().setAllowReturnTransitionOverlap(false);
  1. 在需要动画效果的 Activity中添加如下代码:
    slide.xml引入方式
Transition slide = TransitionInflater.from(this).inflateTransition(R.transition.slide);
getWindow().setEnterTransition(slide);

代码生成方式

android.transition.Slide slide = new android.transition.Slide();
//动画时长
slide.setDuration(500);
//动画从哪个方向执行
slide.setSlideEdge(Gravity.TOP);
//动画的状态:MODE_OUT:退出、MODE_IN:进入
slide.setMode(Visibility.MODE_OUT);
getWindow().setEnterTransition(slide);
  1. 在调起这个 ActivityActivity 中使用如下方式(注意这一步很重要):
// 一定要用这种方式startActivity
startActivity(intent,ActivityOptions.makeSceneTransitionAnimation(activity). toBundle());

然后你就可以看到效果了。

然而事情还没有这么简单,这里只是进入的效果,假如我们指定要从A进入B时,A的退场动画、B的进场动画,B finishi 返回A时,B的返回动画、A的重入动画,那该采用怎样的姿势?

那么我们首先弄清楚四个方法:

• setExitTransition():当 A 启动 B 时, A 离开场景的退出过渡动画,在A中设置
• setEnterTransition():当 A 启动 B 时, B 进入场景的进入过渡动画,在B中设置
• setReturnTransition():当 B 返回 A 时, B 离开场景的返回过渡动画,在B中设置
• setReenterTransition():当 B 返回 A 时, A 进入场景的重入过渡动画,在A中设置

其中,如果 setReturnTransitionsetReenterTransition 方法没有指定,那么会将 setExitTransitionsetEnterTransition 指定的动画反过来执行。
还有要注意的一点是:如果要使B返回A时,A的重入过渡动画(即 setReenterTransition() 方法所设置的动画)和B的返回过渡动画(即 setReturnTransition() 方法所设置的动画)生效,必须在B中使用 finishAfterTransition() 方法退出。

了解了这几种方法的区别之后,我们就好摆姿势了(以下均使用代码创建方式)

  1. 在A Activity 中添加如下代码:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.a);
    setupWindowAnimations();
    findViewById(R.id.toB).setOnClickListener(view -> {
        Intent intent = new Intent(A.this,B.class);
        // 一定要采用这种方式启动B Activity
        startActivity(intent,ActivityOptions.makeSceneTransitionAnimation(A.this). toBundle());
    });
}
private void setupWindowAnimations() {
    android.transition.Explode explode= new android.transition.Explode();
    explode.setDuration(500);
    getWindow().setExitTransition(explode); // A 离开场景的退出过渡动画
    getWindow().setReenterTransition(explode); // A 进入场景的重入过渡动画
    //不允许动画重叠
    getWindow().setAllowEnterTransitionOverlap(false);
    getWindow().setAllowReturnTransitionOverlap(false);
}
  1. 在B Activity 中添加如下代码:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.b);
    setupWindowAnimations();
}
private void setupWindowAnimations() {
    android.transition.Explode explode= new android.transition.Explode();
    explode.setDuration(500);
    getWindow().setEnterTransition(explode); // B 进入场景的进入过渡动画
    getWindow().setReturnTransition(explode); // B 离开场景的返回过渡动画
    //不允许动画重叠
    getWindow().setAllowEnterTransitionOverlap(false);
    getWindow().setAllowReturnTransitionOverlap(false);
}
...
// 退出时调用该方法
finishAfterTransition();

至此,动画效果就可以展现了。