Android转场动画Transition Animation实现记录

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

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

应用场景包括:

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

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

  1. xml设置
    首先我们需要在 AndroidManifest.xml 清单文件中 application 节点使用的theme主题添加属性:
    @style/AnimationActivity

    AnimationActivity的属性如下:

    
    <style name="AnimationActivity" parent="@android:style/Animation.Activity">
    <item name="android:activityOpenEnterAnimation">@anim/in_from_right
    "android:activityOpenExitAnimation">@anim/in_from_right_abit
    "android:activityCloseEnterAnimation">@anim/out_to_right_abit
    "android:activityCloseExitAnimation">@anim/out_to_right
    style>

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

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


进入主题
首先有三种自带的Transition Animation效果(图片来自一个开源项目:动画学习集合):

  • fade
  • slide
  • explode

其次生成的方式有2种:

  1. xml生成
    res 下创建 transition资源文件夹,在该文件夹中创建xml文件,比如:
    slide.xml

    
    <slide xmlns:android="http://schemas.android.com/apk/res/"
      android:duration="500"/>
  2. 代码生成

    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">trueitem>
    
    <item name="android:windowActivityTransitions">trueitem>
    
    <item name="android:windowAllowEnterTransitionOverlap">falseitem>
    <item name="android:windowAllowReturnTransitionOverlap">falseitem>

在指定的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);
  2. 在调起这个 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);
    }
  2. 在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();

至此,动画效果就可以展现了。还有共享元素动画,待实践之后再写一篇记录。

你可能感兴趣的:(Android)