android 动画阻塞,Android转场动画深度解析(2)

紧接着上一篇介绍了Scene和Transition的基本用法后,这篇开始介绍如何运用这些到转场动画中。从A页面到B页面,再从B页面返回到A页面,这就是一个完整的转场过程。而转场动画就是负责来优雅地协调处理好这个过程的。

Content Transition

Content Transition就是最常见的转场动画了。为了方便大家理解,我们先来上个图。

a3ca2721d9f936efad9cc4e99575608e.gif

部分代码:

源Activity:

Slide slide=new Slide();

slide.setDuration(3000);

slide.setSlideEdge(Gravity.BOTTOM);

getWindow().setExitTransition(slide);

Explode explode = new Explode();

explode.setDuration(3000);

explode.setMode(Visibility.MODE_IN);

getWindow().setReenterTransition(explode);

复制代码

目标Activity:

Slide slideEnter=new Slide();

slideEnter.setDuration(1500);

slideEnter.setSlideEdge(Gravity.RIGHT);

getWindow().setEnterTransition(slideEnter);

Slide slide=new Slide();

slide.setDuration(1500);

slide.setSlideEdge(Gravity.RIGHT);

getWindow().setReturnTransition(slide);

复制代码

然后在A页面调用方法跳到B页面:

Intent intent = new Intent(this, BActivity.class);

ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this);

startActivity(intent, activityOptionsCompat.toBundle());

复制代码

可以看到一共可以设置四个Transition:

(1)setExitTransition() - 当A 跳转到 B时,A中的View退出场景的效果(默认Null)

(2)setEnterTransition() - 当A 跳转到 B时,B中的View进入场景的效果(默认Fade)

(3)setReturnTransition() - 当B 返回 A时,B中的View退出场景的效果(默认同EnterTransition)

(4)setReenterTransition() - 当B 返回 A时,A中的View进入场景的效果(默认同ExitTransition)

以上这个过程同样可以看做是Transition作用在Scene上的一系列效果,只不过这里的Scene从上一篇中的单一布局换成了Window。不过细心的同学可能发现了,明明我为四个过程都设置动画效果,可为什么ExitTransition没有生效呢?接下来我们为每个Transition加入监听,看看动画的执行流程。下面是其中一个的代码,其他三个都一样:

Explode explode = new Explode();

explode.setDuration(3000);

explode.setMode(Visibility.MODE_IN);

explode.addListener(new Transition.TransitionListener(){

@Override

public void onTransitionStart(Transition transition) {

Log.d("Transitions--","ReenterTransitionStart");

}

@Override

public void onTransitionEnd(Transition transition) {

Log.d("Transitions--","ReenterTransitionEnd");

}

@Override

public void onTransitionCancel(Transition transition) {

}

@Override

public void onTransitionPause(Transition transition) {

}

@Override

public void onTransitionResume(Transition transition) {

}

});

getWindow().setReenterTransition(explode);

复制代码

再次执行程序,日志信息如下:f2a1fcf38167143f125339dfa0c88163.png

原来A页面的退出动画和B页面的进入动画、B页面的返回动画和A页面的重现动画是并行执行的。也就是说A页面的ExitTransition不是没有执行,而是在它执行的时候,B页面已经覆盖上来,并且EnterTransition已经同时在执行了,这时A页面已经不可见了。这也是Android默认的转场动画执行流程。

那问题来了,如果想要串行执行该怎么办呢?

有两种方法:

在设置Transition的时候同时设置不允许Transition重叠,也就是并行执行:

getWindow().setAllowEnterTransitionOverlap(false);

getWindow().setWindowAllowReturnTransitionOverlap(false);

复制代码

或者在主题文件全局设置这个属性,这样无疑更好,即减少了代码又保证了应用视觉效果的统一:

false

false

复制代码

修改后效果如下:

7492139518c773930929549d6042ddd1.gif

日志也显示现在是串行执行了:

49b654f87e54838e5c0125b1c7348231.png

生命周期分析

保持上面的打印信息不变,我们增加两个Activity的生命周期日志信息,串行结果如下:657cce5e660a78f74daf0466127ee6f6.png

并行如下:

3f8446dfb8751a2d5c306fb5150274a8.png

可以得到如下信息:

在A页面的onPause执行前,ExitTransition就已经开始执行了

Transition不会阻塞BActivity的生命周期,尽管是串行执行的,即使ExitTransition没结束,BActivity已经执行完OnResume了。

ReturnExitTransition需要等到AActivity OnStart执行完才开始执行,而且ReturnExitTransition会阻塞AActivity的生命周期,AActivity的OnResume会等到ReturnExitTransition执行完再执行。关于这点可以简要说明下:直接调用Finish不会有动画直接结束掉,需要执行onBackPressed()才会有ReturnExitTransition。看源码就很明显了:

public void onBackPressed() {

if (mActionBar != null && mActionBar.collapseActionView()) {

return;

}

if (!mFragments.getFragmentManager().popBackStackImmediate()) {

finishAfterTransition();

}

}

复制代码

总结

最后简单分析下转场动画的大致流程(以slide为例),看过上一篇文章的同学应该很好理解:

1.从DecoerView开始,依次遍历获得当前Window上的视图树里的所有View

2.执行captureStartValues(TransitionValues transitionValues),捕获View开始状态的一些属性(visibility,Parent,LocationOnScree)

3.设置所有的VIew为INVISIBLE。

4.执行captureEndValues(TransitionValues transitionValues),捕获View结束状态的一些属性(visibility,Parent,LocationOnScree)

5.比较属性的不同,创建属性动画。下一个过程就是返回属性动画并执行了。

复制代码

这是ExitTransiton的流程,其他三个也差不多。下一篇将会讲带共享元素的转场动画,也是material design中很有特色的动画了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值