Activity的转场动画一共有两种:1、利用Animation;2、利用Transition。
通过之前的学习,我们知道Animation就是补间动画,而Transition是过渡动画框架中的角色,且其底层的实现就是Animator。
在Android 5.0之后,才支持Transition。
我们直接在Activity中调用overridePendingTransition()
即可:
public void overridePendingTransition(int enterAnim, int exitAnim) {
try {
ActivityTaskManager.getService().overridePendingTransition(
mToken, getPackageName(), enterAnim, exitAnim);
} catch (RemoteException e) {
}
}
传入的两个参数,就是对应的Animation动画资源文件。
假设从FirstActivity 跳转至 SecondActivity:
假设从SecondActivity退出返回FirstActivity:
注意: overridePendingTransition()
方法必须在startActivity()
之后调用,或者在finish()
之后调用。
示例代码:
btn_start.setOnClickListener {
startActivity(Intent(this, SecondActivity::class.java))
overridePendingTransition(R.anim.anim_rotate,android.R.anim.fade_out)
}
//重写 finish() 方法是最好的解决办法
override fun finish() {
super.finish()
overridePendingTransition(android.R.anim.fade_in,android.R.anim.fade_out)
}
具体的动画资源如何编写什么的,直接参考补间动画。
你可以旋转进场Activity,甚至可以旋转+缩放+透明 退出Activity。
当然还有一种不推荐使用的办法:直接在Activity的Theme中设置动画:
<style name="AppTheme.FirstActivty" parent="AppTheme">
- "android:activityOpenEnterAnimation"
>@android:anim/fade_in
- "android:activityOpenExitAnimation">@anim/anim_rotate
- "android:activityCloseEnterAnimation">@android:anim/fade_in
- "android:activityCloseExitAnimation">@anim/anim_rotate
style>
<style name="AppTheme.SecondActivity" parent="AppTheme">
<item name="android:windowActivityTransitions">true</item>
</style>
如果你的父主题层层传递,有Theme.Material.* 的话,那么这个属性会默认设置为true。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
with(window) {
requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)
}
setContentView(R.layout.activity_second)
注意:你必须要在setContentView()
之前操作 window
一共有四种状态的动画:Enter、Exit、Reenter、Return。
假设有两个Activity,FirstActivity和SecondActivity。
当FirstActivity ==> SecondActivity
首先FirstActivity会执行Exit动画,然后再执行SecondActivity的Enter动画。
当SecondActivity退出返回至FirstActivity
首先SecondActivity会执行Return动画,然后再执行FirstActivity的Reenter动画。
当然,对于如何设置动画,也有两种方式:
<item name="android:windowEnterTransition">@android:transition/slide_topitem>
<item name="android:windowExitTransition">@android:transition/slide_leftitem>
<item name="android:windowReenterTransition">@android:transition/slide_bottomitem>
<item name="android:windowReturnTransition">@android:transition/slide_rightitem>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
with(window) {
requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)
//注意,根据你支持的版本,使用 android包 或者 androidX包
enterTransition = android.transition.Slide(Gravity.TOP)
exitTransition = android.transition.Slide(Gravity.BOTTOM)
reenterTransition = android.transition.Slide(Gravity.LEFT)
returnTransition = android.transition.Slide(Gravity.RIGHT)
}
setContentView(R.layout.activity_first)
}
startActivity(Intent(this, SecondActivity::class.java),
ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle())
所谓共享元素,并不是真的两个Activity公用一个View,而是通过动画的手段,将两个View看作是一个View。
我们需要分别设置两个Activity中的两个View的transitionName,这两个View可以是不同的View,例如一个是ImageView,一个TextView都是可以的,但是这两个View的transitionName必须是一样的。
activity_first.xml
<ImageView
android:id="@+id/imageView"
... ...
android:transitionName="@string/ts_common_img"/>
================================================================
activity_second.xml
<ImageView
android:id="@+id/imageView"
... ...
android:transitionName="@string/ts_common_img"/>
还是那一段咒语,只不过添加了一点料:
startActivity(Intent(this, SecondActivity::class.java),
ActivityOptionsCompat.makeSceneTransitionAnimation(
this,Pair(imageView,getString(R.string.ts_common_img))).toBundle())
makeSceneTransitionAnimation()
这个方法的第二个参数是个可变参数,你可以传入多个Pair实现多个共享元素的动画效果。这个Pair类的构造方法,第一个参数传的就是View,第二个就是transitionName了。
1、其实Activity的转场动画就这两种了,但是如果投机取巧的话,我们还可以利用揭露动画来实现,戳这里看看。
2、使用Transition来实现转场动画,可以完美的实现两个Activity之间的转场动画,但是也有一些小坑。假设有三个Activity:A、B、C;
A和B都实现了Transition动画,A=>B B=>A 都是正常的,但是如果A=>B B=>C然后C=>B,这个时候A和B之间的过渡动画就会失效。
3、不管是ActivityA到ActivityB还是ActivityB返回ActivityA,两个Activity都会各自执行一个动画,默认情况下,两个动画会是重叠的效果,也就是说会同时执行。如果你觉得不顺眼,想要先后执行的话,可以进行一些设置:
<item name="android:windowAllowEnterTransitionOverlap">falseitem>
<item name="android:windowAllowReturnTransitionOverlap">falseitem>
with(window) {
allowEnterTransitionOverlap = false
allowReturnTransitionOverlap = false
}