属性动画
学习,参考加部分信息拷贝,来自以下链接:
动画原理讲解系列:
http://blog.csdn.net/u013478336/article/details/52137385
牛逼的自定义插值器:
http://www.cnblogs.com/wondertwo/p/5327586.html
Evaluator
http://wiki.jikexueyuan.com/project/android-animation/5.html
http://wiki.jikexueyuan.com/project/android-animation/6.html 讲evaluator字母的变化
牛逼的动画原理讲解,但是没有仔细看的:
http://www.jianshu.com/p/ee7e3d79006d
其他:
http://www.jianshu.com/p/733532041f46
http://blog.csdn.net/lmj623565791/article/details/38067475/
概述
1.1 简述
属性动画引入自Android 3.0(API 11),其原理是给定对象的一个或多个属性,指定其开始与结束时的值,通过时间插值生成不同的属性值,并调用更新方法将属性值设置到对象内,引起对象重绘,从而形成动画效果。比如,通过不断的设置View的宽高来更新View的展示,形成缩放效果等。
1.2 属性动画相关概念
一个属性动画执行需要的基本要素包括:承载动画执行的对象属性、动画持续时间和属性的变化区间。
- Duration: 指定动画的执行时间,默认300ms
- Time interpolation: 一个输入为动画真实时间的函数,以此函数来计算动画属性;其实重点在于函数上,这个函数定义的是动画的变化速率,举个例子来看:假如有个函数y=x,x是动画的真实执行时间,y是映射后的速度,则这个动画是恒速执行的;假如映射函数是y=x*x,这个动画是就是不断加速运行的,因为y的变化速率在不断的增大。
- Repeat count and behavior: 动画重复次数表示动画需要被执行的次数,动画重复时的行为有两种:从头开始或者反转执行;在动画执行结束时,如果没有执行完指定次数,则继续执行;
- Animator sets: 将多个动画效果组成动画集合并设置彼此间的执行顺序,可设三种执行顺序:一起执行、顺序执行和在指定时间执行。
- Frame refresh delay: 指定多长时间刷新一次动画的帧,默认值是10ms一次,但最终取决于当前系统的繁忙程度和系统多快能相应定时器,基本上我们可以不用考虑。
- 监听动画: 开始 / 结束 / 重复时刻
anim.addListener(new AnimatorListenerAdapter() {
// 向addListener()方法中传入适配器对象AnimatorListenerAdapter()
// 由于AnimatorListenerAdapter中已经实现好每个接口
// 所以这里不实现全部方法也不会报错
@Override
public void onAnimationStart(Animator animation) {
// 如想只想监听动画开始时刻,就只需要单独重写该方法就可以
}
});
1.3 属性动画与补间动画的区别
应用对象不同,本质不同,适用范围有包含关系。
- 补间动画的应用对象只能是View,不能用于非View对象,属性动画支持任意对象;
- 补间动画的本质是对View做Transformation,并不能影响View的布局位置,只能影响View的可视位置。如果View从屏幕左边移动到右边,则其展示在右边了,但是这时候View相应点击事件还是在左边的位置,因为View并没有真的移动到右边,只是被绘制到右边了;
- 及时动画对象是View,补间动画能做的也比较有限,只能做平移/旋转/缩放/透明度四种变化效果,假如我们要不断改变View背景色,就搞不定了,属性动画表示毫无压力;
- 属性动画比补间动画更灵活,可以同时支持多个属性的动画,每个属性都可以独立定义插值器,各动画之间还可以做动画同步控制。
1.4 Interpolator vs evaluator
- Interpolator: 插值器, 用来定义animator变化的速率 (加速、减速...)
AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator 开始的时候向后然后向前甩
AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator 动画结束的时候弹起
CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator 在动画开始的时候快然后慢
LinearInterpolator 以常量速率改变
OvershootInterpolator 向前甩一定值后再回到原来位置
-
evaluator: 返回动画在当前时间点所需要的值
我们可以把动画的过程想象成是一部电影的播放,电影的播放中有进度条,Interpolator就是用来控制电影播放频率,也就是快进快退要多少倍速。然后Evaluator根据Interpolator提供的值(fraction)计算当前播放电影中的哪一个画面,也就是进度条要处于什么位置。
1.5 动画的过程中所涉及的计算
-
ValueAnimator对象会根据动画的总时间和已经流逝的时间计算出一个0到1之间的elapsed fraction值。这个elapsed fraction值就代表了时间完成的程度
-
计算出elapsed fraction之后,ValueAnimator对象会调用TimeInterpolator
来计算一个interpolated fraction,即,根据所设置的时间插值方法将elapsed fraction映射到interpolated fraction。 interpolated fraction 可能大于、小于、等于elapsed fraction,就看使用的什么插值器了。 -
interpolated fraction计算出来后,ValueAnimator 会调用TypeEvaluator,来进行你要动画的属性值的计算。
这时候用的输入参数就是interpolated fraction的值,以及属性值的起始值和终止值。
ValueAnimator
- 构造
ValueAnimator.ofArgb
ValueAnimator.ofInt
ValueAnimator.ofFloat
ValueAnimator.ofObject
ValueAnimator.ofPropertyValuesHolder
ValueAnimator animator = ValueAnimator.ofInt(0, 400);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int) animation.getAnimatedValue();
tv.layout(curValue, curValue, curValue + tv.getWidth(), curValue + tv.getHeight());
}
});
animator.start();
PropertyValuesHolder
- 保存了动画过程中所需要操作的属性和对应的值。
- 我们通过 ofInt(Object target, String propertyName, int… values)构造的动画,ofInt()的内部实现其实就是将传进来的参数封装成 PropertyValuesHolder 实例来保存动画状态。
- 在封装成 PropertyValuesHolder 实例以后,后期的各种操作也是以 PropertyValuesHolder 为主的。
自定义ValueAnimator
ObjectAnimator
ValueAnimator 有个缺点,就是只能对数值对动画计算。想对哪个控件操作,需要监听动画过程,在监听中对控件操作。
为了能让动画直接与对应控件相关联,以使我们从监听动画过程中解放出来在 ValueAnimator 的基础上,又派生了一个类 ObjectAnimator;
先看看利用 ObjectAnimator 重写的 ofFloat 方法如何实现一个动画:(改变透明度)
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"alpha",1,0,1);
animator.setDuration(2000);
animator.start();
- 要使用 ObjectAnimator 来构造对画,要操作的控件中,必须存在对应的属性的 set 方法
- setter 方法的命名必须以骆驼拼写法命名,即 set 后每个单词首字母大写,其余字母小写,即类似于 setPropertyName 所对应的属性为 propertyName ;
set 函数调用频率是多少:动画在进行时,每隔十几毫秒会刷新一次,所以我们的 set 函数也会每隔十几毫秒会被调用一次。
系统会根据属性通过反射找到对应属性的设置方法,刷新其值 - 何时需要实现对应属性的 get 函数。构造方法中最后一个参数都是可变长参数,从哪个值变到哪个值的,如果值传入了一个值,那默认值最终值,起始值就从get属性获取。
**自定义ObjectAnimator **
AnimatorSet
- AnimatorSet 针对 ValueAnimator 和 ObjectAnimator 都是适用的;
- playSequentially 表示所有动画依次播放,playTogether 表示所有动画一起开始。
- setTarget属性,在 AnimatorSet 中设置以后,会覆盖单个 ObjectAnimator 中的设置;即如果 AnimatorSet 中没有设置,那么就以 ObjectAnimator 中的设置为准。
自定义Interpolator
public class AccelerateDecelerateInterpolator extends BaseInterpolator
implements NativeInterpolatorFactory {
public AccelerateDecelerateInterpolator() {
}
@SuppressWarnings({"UnusedDeclaration"})
public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();
}
}
换成数学表达式
{0.5*cos[(input + 1)π] + 0.5}
余弦函数.png
在0-1之间,增长速度是先变快,后匀速,最后慢慢变慢