Android动画全篇系列(十一)——Activity转场动画

一、前言

Activity的转场动画一共有两种:1、利用Animation;2、利用Transition

通过之前的学习,我们知道Animation就是补间动画,而Transition是过渡动画框架中的角色,且其底层的实现就是Animator

在Android 5.0之后,才支持Transition

二、利用Animation

我们直接在Activity中调用overridePendingTransition()即可:

    public void overridePendingTransition(int enterAnim, int exitAnim) {
        try {
            ActivityTaskManager.getService().overridePendingTransition(
                    mToken, getPackageName(), enterAnim, exitAnim);
        } catch (RemoteException e) {
        }
    }

传入的两个参数,就是对应的Animation动画资源文件。

假设从FirstActivity 跳转至 SecondActivity:

  • enterAnim 表示SecondActivity进行的动画资源文件。
  • exitAim 表示FirstActivity进行的动画资源文件。

假设从SecondActivity退出返回FirstActivity:

  • enterAnim 表示FirstActivity进行的动画资源文件。
  • exitAim 表示SecondActivity进行的动画资源文件。

注意: 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">
        <item name="android:activityOpenEnterAnimation">@android:anim/fade_in</item>
        <item name="android:activityOpenExitAnimation">@anim/anim_rotate</item>
        <item name="android:activityCloseEnterAnimation">@android:anim/fade_in</item>
        <item name="android:activityCloseExitAnimation">@anim/anim_rotate</item>
    </style>

三、利用Transition

1、开启支持过渡动画
  • 通过Theme来开启
    <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

2、设置具体动画

一共有四种状态的动画:Enter、Exit、Reenter、Return

假设有两个Activity,FirstActivitySecondActivity

  • FirstActivity ==> SecondActivity
    首先FirstActivity会执行Exit动画,然后再执行SecondActivityEnter动画。

  • SecondActivity退出返回至FirstActivity
    首先SecondActivity会执行Return动画,然后再执行FirstActivityReenter动画。

当然,对于如何设置动画,也有两种方式:

  • 通过Theme来设置
<item name="android:windowEnterTransition">@android:transition/slide_top</item>
<item name="android:windowExitTransition">@android:transition/slide_left</item>
<item name="android:windowReenterTransition">@android:transition/slide_bottom</item>
<item name="android:windowReturnTransition">@android:transition/slide_right</item>

  • 通过代码
    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)
    }
3、最后加上一段咒语
startActivity(Intent(this, SecondActivity::class.java),
ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle())
4、共享元素

效果
所谓共享元素,并不是真的两个Activity公用一个View,而是通过动画的手段,将两个View看作是一个View。

1、设置transitionName

我们需要分别设置两个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"/>
2、一段咒语

还是那一段咒语,只不过添加了一点料:

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都会各自执行一个动画,默认情况下,两个动画会是重叠的效果,也就是说会同时执行。如果你觉得不顺眼,想要先后执行的话,可以进行一些设置:

  • 在Theme中
<item name="android:windowAllowEnterTransitionOverlap">false</item>
<item name="android:windowAllowReturnTransitionOverlap">false</item>
  • 在代码中
   with(window) {
            allowEnterTransitionOverlap = false
            allowReturnTransitionOverlap = false
   }
A: 可以使用共享元素转场动画实现这种效果。具体步骤如下: 1. 在两个 Activity 中选定相同的 View 作为共享元素,设置相同的 transitionName。 ```xml <!--activity1--> <ImageView android:id="@+id/shared_element" android:transitionName="shared_element"/> <!--activity2--> <ImageView android:id="@+id/shared_element" android:transitionName="shared_element"/> ``` 2. 在启动 Activity2 时,设置共享元素的转场动画。 ```kotlin // activity1 val intent = Intent(this, Activity2::class.java) // 设置共享元素的转场动画 val options = ActivityOptions.makeSceneTransitionAnimation(this, sharedElement, "shared_element") startActivity(intent, options.toBundle()) ``` ```xml // activity2 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity2) // 设置共享元素的转场动画 ViewCompat.setTransitionName(sharedElement, "shared_element") // 延迟进入动画,等待布局完成 window.decorView.postDelayed({ startEnterAnimation() }, 100) } private fun startEnterAnimation() { val enterAnimation = AnimationUtils.loadAnimation(this, R.anim.translate_in_from_right_bottom) enterAnimation.duration = 500 sharedElement.startAnimation(enterAnimation) } ``` 3. 在 Activity2 中,在退出时设置返回动画,并在动画结束后调用 `finish()` 方法。 ```kotlin override fun onBackPressed() { // 设置返回动画 val exitAnimation = AnimationUtils.loadAnimation(this, R.anim.translate_out_to_left_top) exitAnimation.duration = 500 sharedElement.startAnimation(exitAnimation) // 在动画结束后调用 finish() 方法 exitAnimation.setAnimationListener(object : Animation.AnimationListener { override fun onAnimationStart(animation: Animation?) {} override fun onAnimationEnd(animation: Animation?) { finishAfterTransition() } override fun onAnimationRepeat(animation: Animation?) {} }) } ``` 对应的动画资源文件 `translate_in_from_right_bottom.xml` 和 `translate_out_to_left_top.xml` 可以自己定义,这里提供一组示例: ```xml <!--translate_in_from_right_bottom.xml--> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:fromXDelta="100%p" android:fromYDelta="100%p"/> <!--translate_out_to_left_top.xml--> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:toXDelta="-100%p" android:toYDelta="-100%p"/> ``` 运行效果如下: ![](https://img-blog.csdnimg.cn/2022011319273689.gif#pic_center)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值