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为0 B背景不透明:没有动画效果
B背景透明:没有动画效果
B背景不透明:B有动画效果,A不可见
B背景透明:B有动画效果,A可见,A无动画效果
exitAnim为0 B背景不透明: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的动画效果

Android Activity跳转动画 - overridePendingTransition用法及原理分析相关推荐

  1. android跳转界面动画,Android Activity跳转动画效果

    Activity的跳转动画在5.0的时候做了一个重大的突破,下面来看一下吧 1.5.0之前的overridePendingTransition 相信大家对OverridePendingTransiti ...

  2. Android Activity跳转动画,让你的APP瞬间绚丽起来

    我们都知道绚丽的APP总会给用户耳目一新的感觉,为了抓住用户更大网络公司使出浑身解数让自己的产品更绚丽,而绚丽最简单的效果就是Activity跳转效果,不仅可以让用户看起来舒服,而且实现起来也特别简单 ...

  3. Android activity跳转动画,6种activity进入动画

    源码链接:https://pan.baidu.com/s/1jAKMNUuCdWVxUm2BUCzL2g 添加动画anim 新activity进入方式 默认是右往左进入动画 1.下往上推进入动画--1 ...

  4. Android Activity跳转动画效果

    原生的Activity之间跳转真的是感觉太尴尬了,所以有的时候需要我们去添加一个动画效果,衔接起来看起来友好流畅,废话不说,上代码: 第一步,创建动画文件 注: 在res下创建anim文件夹 1.编写 ...

  5. Android -- 基础篇 -- Activity跳转动画的五种方式(下)

    上一篇文章中我们讲解了在Activity启动过程中获取组件宽高的五种方式.在Activity的启动过程中如果我们直接在生命周期方法中通过view.getWidth()或者是view.getHeight ...

  6. Github项目解析(九)--实现Activity跳转动画的五种方式

    2019独角兽企业重金招聘Python工程师标准>>> 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请标明出处:一片枫叶的专栏 上一篇文章中我们讲解了在Activity ...

  7. android activity跳转多次闪退_Android实现Activity和Fragment的跳转动画

    1.使用overridePendingTransition方法实现Activity跳转动画 botton_in <?xml version="1.0" encoding=&q ...

  8. android activity的跳转动画,实现activity跳转动画的若干种方式

    第一种: (使用overridePendingTransition方法实现Activity跳转动画) 在Activity中代码如下 /** * 点击按钮实现跳转逻辑 */ button1.setOnC ...

  9. Android 9.0去除Activity跳转动画

    有客户要求界面跳转风格要统一,第三方的APP无法控制,所以需要从系统层把Activity跳转动画禁用 frameworks/base/services/core/java/com/android/se ...

最新文章

  1. linux系统中文件编程,Linux当中的文件系统
  2. Batch Normalization的TensorFlow实现
  3. 我的职业发展目标计算机作文,作文《我的职业发展目标》1000字
  4. 使用Github(创建仓库、仓库主页说明)
  5. javascript基础学习一--面向对象
  6. Analyzing Storage Performance using the Windows Performance Analysis ToolKit (WPT)
  7. Java程序员需要掌握哪些技能才能通过大公司的面试
  8. eclipse安装Freemaker IDE插件
  9. 使用Nmon监控Linux的系统性能
  10. 利用HTML和CSS做的简历模板
  11. java jisuan da xie zi mu ge shu_java获取中文拼音
  12. Echarts — 绘制省级地图
  13. 映射表类(CMap)
  14. Hive查询问题(卡住)
  15. platform创建说明
  16. 长安大学计算机学硕毕业要求,长安大学研究生学习期间发表学术论文规定.doc...
  17. jQuery判断email地址 邮箱地址 email regex
  18. 思科isis路由的优先级_ISIS路由基本配置实验
  19. JVM:方法调用之动态类型语言支持。
  20. 转云风的博客——无欲则刚

热门文章

  1. 2020-09-01 关于shiro的org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager异常
  2. 整体功能大于部分功能之和_功能性思考,第2部分
  3. python列表的嵌套_Python-嵌套列表list的全面解析
  4. Oracle RAC的启动和关闭
  5. 嵌入式linux开启无线热点模式(AP),联机设备通过 wifi 热点访问外网
  6. QT Quick 简介
  7. 星淘惠:亚马逊仍是跨境电商主流深化选品才能做到事半功
  8. 学术会议论文查重吗_学术论文会论文查重吗?
  9. (9) IFC中的聚合关系(IfcRelAggregates) (Industry Foundation Class)
  10. 计算机毕业设计ssm双峰县在线房屋租售网站