Transition动画效果诞生于Android 4.4,主要负责:
- 捕捉在开始场景和结束场景中每个 View 的状态。
- 根据视图一个场景移动到另一个场景的差异创建一个 Animator。
应用场景包括:
- 可以在activity之间跳转的时候添加动画
- 动画共享元素之间的转换活动
- activity中布局元素的过渡动画
我们以前实现Activity切换过程的动画的姿势是这样的:
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
中创建对应的文件即可。代码设置
通过在Activity中重写overridePendingTransition
给当前界面添加进入、退出动画,具体自行搜索,因为这篇博客的重点是在 Transition Animation 上。
进入主题
首先有三种自带的Transition Animation效果(图片来自一个开源项目:动画学习集合):
- fade
- slide
- explode
其次生成的方式有2种:
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"/>
代码生成
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的姿势如下:
在
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);
在需要动画效果的
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);
在调起这个
Activity
的Activity
中使用如下方式(注意这一步很重要):
// 一定要用这种方式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中设置
其中,如果
setReturnTransition
和setReenterTransition
方法没有指定,那么会将setExitTransition
和setEnterTransition
指定的动画反过来执行。还有要注意的一点是:如果要使B返回A时,A的重入过渡动画(即
setReenterTransition()
方法所设置的动画)和B的返回过渡动画(即setReturnTransition()
方法所设置的动画)生效,必须在B中使用finishAfterTransition()
方法退出。
了解了这几种方法的区别之后,我们就好摆姿势了(以下均使用代码创建方式):
在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); }
在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();
至此,动画效果就可以展现了。还有共享元素动画,待实践之后再写一篇记录。