Android Activity跳转动画 - overridePendingTransition用法及原理分析

overridePendingTransition()是在Activity类中实现的一个用来实现跳转动画的方式,也是最常使用的方法。

overridePendingTransition()

先看这个名字,这个方法名很长,由三个单词组成,override是重写,覆盖的意思,pending表示即将到来的,transtition表示过渡,转换,也就是过渡动画的意思。三个单词连起来的意思就是覆盖即将到来的跳转动画,也就是可以通过这个方法添加的跳转动画会覆盖掉即将到来的跳转动画效果。即将到来的这个词很有意思,它表示即使不使用overridePendingTransition(),也会存在Activity切换动画,这个切换动画可能来自于其他方式添加的跳转动画,也可以来自于系统自带的默认动画。事实上,即使不通过本文介绍的任何方法添加Activity跳转动画,Activity也会有默认的跳转动画,这个默认的跳转动画定义在Android主题中。在android:Theme主题中可以看到这样一句样式定义,正是这句为App中所有Activity添加了一个默认的切换动画。

<item name="windowAnimationStyle">@style/Animation.Activity</item>

不过需要注意的是,@style/Animation.Activity中定义的动画样式在不同的系统版本上会有所不同,此外部分Theme自定义了新的windowAnimationStyle,所以默认的Activity动画并非一定是@style/Animation.Activity中定义的样子。

overridePendingTransition()使用方法

Activity的切换动画从业务层面上来说可以分为两种,一种是Activity启动时的动画,一种是从Activity返回时的动画,它们都可以通过overridePendingTransition()来设置,要设置启动时的动画需要在执行startActivity()或startActivityForResult()之后调用overridePendingTransition(),要设置返回时的动画需要在finish()之后调用overridePendingTransition()。启动动画和返回动画是相互独立的,设置启动动画不会对返回动画产生影响,如果只在startActivity()或startActivityForResult()之后调用了overridePendingTransition(),没有在finish()的时候调用,则Activity返回的时候仍然是默认的动画效果,也可以在finish()的时候使用和启动时不同的动画效果。

由于startActivity()和startActivityForResult()本质上是一样的,为了表述方便,后文不再提到startActivityForResult(),所有使用startActivity()的地方都可以用startActivityForResult()。

overridePendingTransition()只能作用在通过startActivity()和finish()方式启动和结束Activity的场景下,其他情况下的Activity创建和退出是不会有任何效果的。例如通过recreate()重建Activity,在其后执行overridePendingTransition()是没有动画效果的。

overridePendingTransition()的调用时机

注释和官方文档中关于此方法调用时机都写到“Call immediately after one of the flavors of startActivity(Intent) or finish to specify an explicit transition animation to perform next.”,也就是说此方法需要在startActivity() 或者finish()方法之后立即调用。因此标准的写法应当是这样的。注释和官方文档中关于此方法调用时机都写到“Call immediately after one of the flavors of startActivity(Intent) or finish to specify an explicit transition animation to perform next.”,也就是说此方法需要在startActivity() 或者finish()方法之后立即调用。因此标准的写法应当是这样的。

在这里插入图片描述
在这里插入图片描述

对一个Android Activity来说,除了可以调用finish()来结束之外,它还可以被Android的返回键所结束。在按下返回键后,会执行到onBackPressed()方法,在onBackPressed()方法中会自动调用finish()方法结束Activity。所以在添加Activity返回动画时,除了要在所有调用finish()的地方调用overridePendingTransition()之外,还要重写onBackPressed()方法,在执行super.onBackPressed()之后调用overridePendingTransition()。由于onBackPressed()总是在最后一步执行finish(),所以如下代码和执行完finish()后调用overridePendingTransition()是等同的。

在这里插入图片描述

immediately的含义通常被理解为调用startActivity()或finish()之后的下一行代码就必须调用overridePendingTransition()才能让动画效果生效。但事实上overridePendingTransition()可以推迟到startActivity() 或finish()之后的某个地方执行。

对启动Activity来说,overridePendingTransition()通常可以放到被启动Activity的onCreate()中来执行,很多文章都说overridePendingTransition()只能在调用super.onCreate()之前执行,这大部分情况是正确的,但并不是说overridePendingTransition()放到super.onCreate()之后就一定没有效果,事实上甚至可以把overridePendingTransition()放到onResume()来执行,这在很多时候是可以有效果的。

对结束Activity来说,finish()之后的overridePendingTransition()执行时机要严格很多,首先并不能将overridePendingTransition()推迟到onDestroy()中执行,也不能在finish()和overridePendingTransition()之间执行一些耗时的代码,但增加一些简单的处理逻辑通常是不会有问题的。

为了避免在不同设备上的差异,减少意外的发生,应当按照官方要求在startActivity() 或finish()方法之后立即调用overridePendingTransition(),对启动Activity来说,最迟应当放到被启动的Activity的onCreate()方法中执行super.onCreate()之前,对结束Activity来说,只能在finish()之后和super.onBackPessed()之后执行。

如果在Activity还未显示完成就调用startActivity()启动另一个Activity,这时在startActivity()之后调用overridePendingTransition()来设置启动动画是不会有效果的,例如在onCreate()中调用startActivity()和overridePendingTransition()就不会有动画效果,这时连默认的动画效果都不会有,被启动的Activity会直接显示出来。

overridePendingTransition()方法参数解析

overridePendingTransition()方法的定义如下。

public void overridePendingTransition(int enterAnim, int exitAnim)

它包含两个参数,分别为enterAnim和exitAnim,它们都是定义在anim文件夹中的某个动画资源的id。overridePendingTransition()方法只有一个定义,没有其他重载的方法,也就是说overridePendingTransition()设置的动画效果只能通过anim资源的方式来定义,无法通过代码创建。

enterAnim用来设置即将进入的Activity的动画效果,而exitAnim用来设置即将退出的Activity的动画效果。当从A启动B时,A是退出的Activity,B是进入的Activity,当从B返回A时则正好相反,A是进入的Activity,B是退出的Activity。也就是说,从A启动B时,B的动画效果是enterAnim,A的动画效果是exitAnim,从B返回A时,B的动画效果是exitAnim,A的动画效果是enterAnim。

在Android系统自带了两组动画效果,分别为fade_in/fade_out和slide_in_left/slide_out_right。可以通过如下代码来使用。

overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);

overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);

设置有如下场景,有三个Activity,分别为A,B和C,A启动B,B启动了C,但B启动C的之后立刻调用了finish()结束了自己,代码如下。这里overridePendingTransition()既在startActivity()之后执行,又在finsh()之后执行,这时动画效果究竟会如何展现呢?

Intent intent = new Intent(B.this, C.class);
startActivity(intent);
finish();
overridePendingTransition(R.anim.anim_down_in, R.anim.anim_down_out);

回答这个问题关键还在于理解overridePendingTransition()本身和enterAnim和exitAnim这两个参数的意义。
在前面我们有提到,Activity的切换动画分为两种,一种是Activity启动时的动画,一种是从Activity返回时的动画,但对overridePendingTransition()来说,它其实并不区分这两种动画类型,无论在startActivity()之后还是在finish()之后执行,它的结果都是一致的,overridePendingTransition()只是为即将到来的Activity切换添加动画效果,也就是为即将进入的Activity执行enterAnim动画,为即将退出的Activity执行enterAnim动画。所以只需要知道上述场景下哪个是即将进入的Activity,哪个是即将退出的Activity即可。显然在上述场景下,C是即将进入的Activity,B是即将退出的Activity,所以动画效果就是C执行enterAnim,B执行exitAnim。

上述enterAnim和exitAnim的值都允许为0,如果enterAnim值为0,表示没有enter动画效果,如果exitAnim为0表示没有exit 动画效果。如果两者都为0,则既没有enter动画效果,也没有exit动画效果,也就是不会有切换动画。但如果两个参数只有一个为0,则实际显示情况会比较复杂。

这里仍以A和B两个Activity为例,首先看A启动B的时候,如果执行overridePendingTransition(0, R.anim.anim_down_out);,也就是enterAnim为0,它表示没有enter动画效果,这时B会直接显示出来,而exitAnim不为0,也就是说A会有一个down_out的动画效果,然而B的界面是覆盖在A之上的,那么显然即使A执行了down_out动画,也是无法看到这个效果的。所以这时从视觉上看是不会有任何动画效果的。我们知道Activity所依附的Window是存在背景的,正是这个背景使得我们无法透过当前Activity看到下层的Activity,那么如果将B设置为一个透明背景的Activity,是否意味着就可以看到A执行down_out的动画效果呢。实践结果告诉我们,如果B的背景是透明的,我们能够透过B看到A,但在B直接显示出来之后,A压根就没动,任何看不到任何动画效果。

再来看overridePendingTransition(R.anim.anim_down_in, 0);,由于exitAnim为0,所以A是没有动画效果的,而B会有一个down_in的动画效果,这时在视觉上看到的会是B从底部升起,但在B逐渐升起的过程中,上面尚未被覆盖的部分并不能看到A的内容,而是一大块的黑色。这时如果B的背景是透明的,则会发现在B升起的过程中没有了黑色的部分,而是能够看到A的内容了。

再来看Activity返回的时候,如果执行overridePendingTransition(0, R.anim.anim_down_out);,这时没有enterAnim效果,只有exitAnim,而B是那个退出的Activity,所以B会有一个动画效果逐渐往下退出,而在B退出的过程中我们也是看不到A的,能看到的只是上方的一大块黑色。这时如果B是透明的,则能看到A就一直显示在B的下方,一动不动。如果执行overridePendingTransition(R.anim.anim_down_in, 0);,我们会看到B直接不可见,A从下方升起,A升起过程中上面同样是黑色的背景。奇怪的是,如果这时将B背景设置为透明,并非黑色的背景被取代,而是整个动画过程不可见。

上述过程总结如下。

启动Activity返回Activity
enterAnim为0B背景不透明:没有动画效果
B背景透明:没有动画效果
B背景不透明:B有动画效果,A不可见
B背景透明:B有动画效果,A可见,A无动画效果
exitAnim为0B背景不透明:B有动画效果,A不可见
B背景透明:B有动画效果,A可见,A无动画效果
B背景不透明:A有动画效果,B不可见
B背景透明:没有动画效果

在之前关于overridePendingTransition()动画的介绍中,都认为overridePendingTransition()动画是以Activity作为对象的,进入的Activity执行enterAnim,退出的Activity执行exitAnim,但如果是这样,上述现象有几个地方会无法解释。

  1. 在启动Activity,enterAnim为0,B背景透明时为何看不到A执行exitAnim
  2. 在返回Activity,extiAnim为0,B背景透明时,为何看不到A执行enterAnim

为了理解上述现象,只能从源码去看overridePendingTransition()究竟是如何实现Activity切换动画的。跟踪了一下,无奈其实现实在是过于复杂,网上资料也几乎没有,所以这里只好对其原理做个推测了。

  1. overridePendingTransition()并没有对Activity实现动画,所有的动画都是在View层面执行的。
  2. overridePendingTransition()执行的动画始终都在B中,无论是从A启动B,还是从B返回A,A始终是不变的。当从A启动B时,A会将自身显示做一个快照,将这个快照对象传递给B。从B返回A时,所谓A的进入动画,仍然是使用之前A传过来的这个快照,并非使用A实时的显示。
  3. 在B中,A的退出和进入动画都是通过背景实现的,它会将A传过来的快照和黑色的背景拼接在一起,按照设定的动画效果来显示,所以如果将B的背景设置为透明,则整个背景变得不可见,所以不会有任何A的动画效果。这就解释了上述问题,当B背景透明时,是不会看到A执行extiAnim和enterAnim的。
  4. 在B中,B的进入和退出动画实际上是对BcontentView的动画效果
  • 14
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Android Activity跳转动画是指在Activity之间切换时,为了增强用户体验而添加的动画效果。常见的跳转动画有淡入淡出、滑动、旋转等。可以通过在代码中设置Activity的进入和退出动画来实现。例如: 1. 淡入淡出动画 在res/anim目录下创建fade_in.xml和fade_out.xml两个文件,分别表示Activity进入和退出时的动画效果。 fade_in.xml: ``` <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:fromAlpha="0.0" android:toAlpha="1.0" /> ``` fade_out.xml: ``` <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:fromAlpha="1.0" android:toAlpha="0.0" /> ``` 在代码中设置Activity的进入和退出动画: ``` startActivity(intent); overridePendingTransition(R.anim.fade_in, R.anim.fade_out); ``` 2. 滑动动画 在res/anim目录下创建slide_in.xml和slide_out.xml两个文件,分别表示Activity进入和退出时的动画效果。 slide_in.xml: ``` <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="500"/> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="500" /> </set> ``` slide_out.xml: ``` <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="0" android:toXDelta="-100%p" android:duration="500"/> <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="500" /> </set> ``` 在代码中设置Activity的进入和退出动画: ``` startActivity(intent); overridePendingTransition(R.anim.slide_in, R.anim.slide_out); ``` 以上是两种常见的Activity跳转动画,开发者可以根据需要自定义动画效果。 ### 回答2: Android平台的Activity是应用程序中最重要的部分之一。当我们需要在应用程序中切换不同的Activity时,我们可以使用跳转动画来创建更加平滑和丰富的用户交互体验。本文将重点介绍如何在Android应用程序中实现Activity跳转动画。 1. 系统默认动画 Android系统提供了一些默认的Activity跳转动画,包括从右往左滑动、从左往右滑动、从上往下滑动、从下往上滑动等。我们可以在Intent中使用setFlags方法来设置跳转动画,例如: intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); startActivity(intent); overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out); 2. 自定义动画 除了系统默认动画,我们还可以根据自己的需求来创建自定义的Activity跳转动画Android系统提供了一些动画资源文件,包括translate、scale、rotate和alpha四种类型。我们可以通过在res目录下的anim文件夹中创建xml文件来定义自定义动画,例如: <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <translate android:fromXDelta="0%" android:toXDelta="100%" android:duration="500"/> </set> 我们在代码中使用以下方法来启动Activity和设置动画: Intent intent = new Intent(MainActivity.this, SecondActivity.class); startActivity(intent); overridePendingTransition(R.anim.slide_in, R.anim.slide_out); 其中,slide_in.xml和slide_out.xml分别是进入和退出Activity时的动画,可以根据自己的需要来定义。 总结:以上是Android中实现Activity跳转动画的方法。在实践中,我们可以根据实际需求来选择系统默认动画或自定义动画,以提升用户体验。在创建自定义动画时,需要注意动画类型的选择和动画时长的设置,以达到最佳效果。 ### 回答3: AndroidActivity跳转动画是指系统在跳转Activity时所播放的动画效果。Android提供了许多内置的跳转动画效果,例如淡入淡出、左/右滑入、翻转、放缩等等。除了这些内置的动画效果,我们还可以自定义Activity跳转动画,以满足个性化需求。 在实现Activity跳转动画时,我们通常需要在startActivity()或finish()方法中添加相应的动画参数。例如,当从Activity A跳转Activity B时,我们可以在startActivity()方法中添加以下代码: ``` startActivity(intent); overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left); ``` 其中,R.anim.slide_in_right和R.anim.slide_out_left是我们自定义的两个动画效果,表示Activity B从右侧滑入,Activity A从左侧滑出。这两个动画效果需要我们在res文件夹下创建anim文件夹,并在该文件夹下添加相应的XML文件。 slide_in_right.xml的代码如下: ``` <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="500"/> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="500" /> </set> ``` slide_out_left.xml的代码如下: ``` <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <translate android:fromXDelta="0" android:toXDelta="-100%p" android:duration="500"/> <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="500" /> </set> ``` 可以看到,slide_in_right.xml描述了Activity B从右侧进入的动画效果,其中包括了平移和透明度渐变两个动画效果。而slide_out_left.xml描述了Activity A从左侧离开的动画效果,同样包括了平移和透明度渐变两个动画效果。 除了基本的平移、透明度渐变效果之外,我们还可以使用缩放、旋转等复杂的动画效果来实现更丰富的跳转动画效果。需要注意的是,动画效果的实现需要考虑到用户体验和性能问题,避免出现卡顿或者过多的动画效果影响用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值