TypeEvaluator的中文翻译为类型估值算法,也叫估值器,它的作用是根据当前属性改变的百分比来计算改变后的属性值。系统也预置了一些估值器。
插值器和估值器的作用是让动画进行非匀速运动。
这是一组动画从0到40ms完成的一个匀速动画,这时候我们要去修改这个动画变成非匀速动画。
动画的默认刷新率是10ms/帧,所以动画有5帧,以第三帧 x=20来说,时间流逝的百分比是50%(20/40=0.5),意味时间过了一半。那x应该改变多少呢?这个就要有插值器和估值器来进行确定。一般情况下的插值器是线性插值器,当时间流逝一半时,x的改变也是一半,所以是0.5,所以线性插值器实现的是匀速动画。
这里是线性插值器(LinearInterpolator)的源码,可以看到getInterpolation中返回的值和输入的值一样,当返回值是0.5,说明输入值也是0.5。而x具体变成具体什么值,就要看估值器。
evaluate方法中的三个参数为估值小数,一个为起始值,一个为结束值。对应t=20ms的例子来说就是evaluate(0.5,20,40),返回得值为20,所以x=20,这就是由来。
由代码又知道,我们可以通过去实现接口Interpolator和TypeEvaluator来自定义插值器和估值器。
属性动画监听器
属性动画提供了监听器用于监听动画的播放过程。主要有如下两个接口:
AnimatorUpdateListener和AnimatorListener。
AnimatorListener可以监听动画的开始、结束、取消和重复播放。
AnimatorUpdateListener会监听整个动画过程,即每走一帧,就会监听一帧。
对任意属性做动画
属性动画要求动画作用的对象提供该属性的get和set方法,属性动画根据外界传递的该属性的初始值和最终值,以动画的效果多次去执行set方法。每次传给set方法的值都不一样,随着时间推移,这个值将越来越接近最终值。所以我们对object的属性abc做动画,如果想让动画生效,要同时满足两个条件:
(1)object必须要提供setAbc方法,如果动画没有提供初始值,还要提供getAbc方法。
(2)object的setAbc对属性abc所做的改变必须能够通过某种方法反映出来,比如会带来UI的改变之类的(否则动画无效果但不会crash)。
比如我们给以一个button来加一个变宽的动画,button的getWidth能够得到width,但是setWidth却不能改变width,因为在button继承的TextView中的setWidth是设置最小宽度和最大宽度,所以满足了第一个条件没有满足第二个条件。解决方法有:
(1)如果你有权限就给你的属性加上set和get方法。
(2)用一个类来包装原始对象,间接为其提供get和set方法。
(3)采用ValueAnimator,监听动画过程,自己实现属性改变。
属性动画的工作原理
这里就不贴源码了,其实很简单,就是判断先将当前动画、等待动画、延迟动画中有和当前动画相同的动画,则将其取消,最后将当前动画start。
使用动画的注意事项
- OOM
帧动画中出现了大量的尺寸过大的图片
- 内存泄漏
有些动画会无限循环,所以要在Activity退出时及时停止。
-
兼容性问题
-
View动画问题
View动画是对动画做影像动画,并没真正改变View的状态
-
不要使用px
-
动画元素的交互
属性动画的单击事件触发在移动后的位置,View则在之前的位置。
- 硬件加速
使用动画的过程中尽量使用硬件加速,能保证动画的平滑和流畅性。
理解Window和WindowManager
Window是一个窗口,Window的具体实现位于WindowManagerService中,WindowManager可以管理Window,并以IPC的形式与WindowManagerService交互。
首先使用WindowManager来添加一个Window,代码如下:
上述的代码将一个Button添加屏幕的(100,300)坐标上。
WindowManager.LayoutParams中的flags和type这两个参数比较重要。