Android共享元素场景切换动画的实现

来源:互联网 发布:ktv网络点歌系统 编辑:程序博客网 时间:2024/05/17 09:14
今天跟大家分享的是场景切换的共享元素,源码已经上传到github:

https://github.com/huzenan/EasyTransition


我们知道安卓5.0系统引入了共享元素,能做出非常炫酷的场景切换效果,这让人非常兴奋同时非常蛋疼,因为低版本没法使用啊,所以今天就跟大家分享一下自己写的一个库,其实只有2个文件而已,还是叫它工具比较合适吧......非常轻量级,简直是人畜无害,兼容安卓5.0以下的版本。

什么都不多说,先看看效果:




效果图涉及了Activity中的元素(顶部bar)和ListView中的元素(icon和name),事实上无论哪个位置的元素都能轻松实现。



用法:


使用这个工具非常简单,假设有ActivityA(简称A)和ActivityB(简称B),在A中启动B,再从B回退到A,首先需要在A和B中,各自定义id相同的两个View,这里可以是ListView的item布局中的View,只要获取到View即可,然后:


·A启动B:


·B回退到A:


用法非常简单,当然以上只是最少参数的基本用法,除此之外可以设置的参数还有时间、加减速以及动画监听,其中动画监听可以方便在动画开始前做一些初始化操作,以及动画结束后做一些显示操作,下面就来讲一下实现的原理。



原理:

从A启动B时,首先需要构造一个EasyTransitionOptions对象,直接通过EasyTransitionOptions.makeTransitionOptions方法进行构造,传入的参数为ActivityA以及需要共享的元素View,我们看一下EasyTransitionOptions有啥:



可以看到前两个即为构造时传入的参数,第三个attrs接下来会用到。

接着我们跟往常一样,构造一个Intent对象,然后调用EasyTransition.startActivity方法,传入了该Intent以及前面构造好的options,我们看看EasyTransition.startActivity做了什么:



首先调用了options.update方法,接着又获取了options的attrs并放到intent中,看看update方法:




就是这里,options使用传入的View填充了之前看到的那个ViewAttrs集合attrs,attrs存储了View的一些属性,分别为:



id用于获取B中的对应的View,接下来会讲到。startX和startY分别为View在A中的x、y坐标,这里通过View的getLocationOnScreen方法获取View在屏幕中的坐标,可以看到该方法的参数为int[] outLocation,以out开头的参数,意思即为执行方法后将填充该参数。width和height分别为View在A中的宽和高。


接下来通过options获取Activity并调用真正的startActivity方法,然后再调用overridePendingTransition(0, 0)将系统的转场动画覆盖,0表示没有转场动画。

然后进入到B,我们在B的onCreate方法中,只调用了一个方法EasyTransition.enter,看看这个方法做了什么:



这个方法有很多个重载,最简单的只需要传入一个Activity参数即可。参数都很简单,分别为ActivityB,动画时间,动画的差值器以及动画监听。

首先通过Activity获取到Intent并拿到从A传入的ViewAttrs集合,接着执行了runEnterAnimation方法,到这里就要开始执行动画了,看看runEnterAnimation方法:



看似挺长的,其实只做了一件事,即根据ViewAttrs集合attrs,给B中的View先设置属性,再执行一段动画

首先遍历attrs,通过id找到B中对应的View;然后在ViewTreeObserver.OnPreDrawListener中设置View的属性,其中scale属性设置为A中View的宽高与B中View的宽高的比,transition属性设置为A中View的坐标相对于B中View的坐标的偏移量,之所以使用屏幕坐标就是为了准确地算出坐标的偏移量,而不受状态栏等其他因素的影响。

设置完成后,再调用View.animate方法,将动画结束状态设置为View在B中的初始状态,再传入时间、动画差值器以及监听器,就这样简单地完成了转场动画。

接着我们需要从B回退到A,在回退的操作中,调用了EasyTransition.exit方法,看看它做了什么:



看起来跟enter方法差不多,通过Activity获取到Intent,再拿到ViewAttrs集合,是的它又派上用场了,接着执行了runExitAnimation方法,可以看到也是挺眼熟的:



也是遍历attrs,找到B中对应id的View,只不过这次动画是从View在B中的初始状态开始,变到View在A中的状态,属性还是那些属性,没有啥其他的。不一样的是,在执行动画后需要关闭B,所以调用了View.postDelayed方法,然后finish掉当前的Activity,依旧是覆盖一下系统的转场动画overridePendingTransition(0, 0)。

就这样简单的实现了共享元素炫酷的转场动画,最初纠结于如何实现比较优雅,然后开始看5.0共享元素有关的那部分源码(也只是粗略看了一下),再看了看网上一些其他人的做法,最终提炼出了这个工具,非常轻量,用起来也挺舒服的。
阅读全文
0 0
原创粉丝点击