view中除了必要的移动之外,也可以使用动画来完善视觉效果。android中的动画在2.3之前只有帧动画和补间动画。3.0之后就加入了属性动画。其实说到动画是什么?就是一个连续的view的集合。帧动画是不断的切换view,补间动画就是不断的绘制两个状态之间的view,形成补间内容。属性动画实际上是加强了动画,在之前的基础上更加灵活,几乎实现了任何有属性的对象的动画效果。其实原理也很简单就是两个状态之间的不断变化。
tip:关于3.0之前动画插值器的历史:2.3的时候补间动画的插值器interpolater接口有getInterpolation(float input)方法,后来3.0之后就是去掉了,然后做了一个父类接口TimeInterpolator,我不知道google工程师门有什么意图,但是我感觉就是为了扩展,说明现在的interpolater都是基于时间上的插值,并且这个插值器知道能是使用在alpha, scale, translate, rotate的极少的属性上。
动画是基于两个状态的不断变化而形成的,这个变化一定有变化规律,这个规律就是用interpolater来得到的值。这个也叫做插值器,就是这个作用。说到动画就不得不提补间动画和属性动画的区别:为什么补间动画只能支持alpha, scale, translate, rotate。愿意就是生成这个两种动画的机制不同。补间动画是通过把动画设置给view然后通过view的不断绘制,期间改变view画的位置然后得到的动画效果。这个效果是不改变属性的,也就是说只是改变了view出现的位置,而没有改变具体的属性。但是属性动画就不同了,他通过改变的是你传递进去的属性值,也就是把两个属性值要进行不断的改变,最后实现内容补间。这也就是为什么属性动画更加强大了,因为他更加抽象粒度更小。小到了属性值。补间动画操作的是view。
补间动画:
要实现一个补间动画有两种方式,代码和xml。了解了view的绘制,实际上任何的一个xml配置的项目你都明白可以通过代码来实现,也就是说xml最终都要使用代码设置对象来实现处理。xml配置的时候,要使用AnimationUtill来进行load进来一个xml,其实就是转化为一个animation对象。然后这个对象可以设置到view中,但是你发现了一个奇怪的现象,view中只是设置了animaiton,但是draw的时候根本就没有使用,实际上又想起一个问题来,为什么viewgroup中没有让复写draw?其实这里有一个drawchild方法就是绘制view的时候所注意的东西。里面包含了动画的绘制,为什么要这样?实际上view的动画是由viewgroup来实现的,viewgroup的会操作view的画布来进行矩阵变换。然后做出动画的动作。这里也就是说明了为什么不会改变view的属性,他变换的是view的canves。而不是属性。
这里还有一个就是animation里面的transfromation,这个是用来改变绘制矩阵的,transfromation里面有一个alpha对象和matrix矩阵是用来操作canves的。也就是说当你使用animation的时候,会将transfromation的属性不断地按照interpolator里面的变化规律来进行变换,这样得到的值还是一个transfromation,然后view的canves就按照transfromation里面的数据矩阵和alpha值来进行了一个变换,这样就形成了动画。这里也就是为什么补间动画只有那4种了。
tip:在使用动画的时候可能会遇到传递type,这个type有3个:1.绝对的absolute,这个实际上就是说你传递的值是绝对的像素。2相对于自己,这里说的意思就是移动和变换的参考都是自己,比如移动1,就是移动1个自己的width。3相对于父类,移动时候会参考父类布局,移动的时候会移动父类布局的宽度。
知道了动画的原理之后,还有几个类比较重要:1.animationset,这个可以把多个动画组合在一起使用。使用的时候会根据你的组合顺序来进行变换动画,其实就是绘制canves。2.layoutAnimation,这个实际就是layout可以再布局的时候利用layoutanimation来进行一个布局动画的显示,但是假如你还设置了里面的view的动画,就会导致view的动画不可用。
属性动画:
还是先介绍一下除了属性动画的插值器,还有一个计算器TypeEvaluator<T>里面有一个函数:public
T evaluate(
float
fraction, T
startValue, T
endValue);
意思就是说fraction是一个变换比例值,从startValue变化到endVaule。
属性动画还是有自己的类,就是ValueAimator,属性动画不同于补间动画,他是基于本身的一个animationHandler来实现的,也就是说属性动画所在的线程必须有looper。当你开始动画的时候,就会调用start,这个时候就会发送一个开始的消息。然后会根据你的插值器和计算器计算的时间比率和属性变化率进行一个属性值的渐变。然后在帧消息函数中做出处理。这样你的属性值就是渐变了。当然要引起视觉变化就要使用animationupdatelistener来进行一个变化的监听。可以获得当前的属性的值。
在valueanimation基础上又封装了objectanimation。这个要使用必须有2个条件:1.有可以使用setget设置的属性,2,属性可以引起变换。当然第二个条件不是必须的,但是你要变换出效果就必须的了。另外可能有这样的情况,我的view没有这个属性set,get方法,这个时候就要使用包装来自己定义属性。或者是你也可以直接使用valueanimation来进行变换。
注意的就是属性变化变化的是属性,当你是使用view来进行属性变换的时候,也就是说你的view属性操作了,不仅仅是操作你的canves了。
view间的动画切换:viewfliper,这个是主要用来进行两个view间的切换动画的实现的,可以自动播放。实际上就是里面有一个消息处理函数,然后发送延时消息,而不断的切换当前显示的view,在切换的时候使用预先设置好的动画效果。由于是加强了,考虑了多种情况,尤其是在屏幕锁屏的时候关闭view切换,使用了boolean标志位来进行区分mstop和mstart,这一点是值得学习的。这也是一个很方便的类。