帧动画
视图动画
llGroup = (LinearLayout) findViewById(R.id.ll_group);
// 创建动画集合
AnimationSet aniSet = new AnimationSet(false);
// 透明度动画
AlphaAnimation alpha = new AlphaAnimation(0, 1);
alpha.setDuration(4000);
aniSet.addAnimation(alpha);
// 旋转动画
RotateAnimation rotate = new RotateAnimation(0, 360,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(4000);
aniSet.addAnimation(rotate);
// 缩放动画
ScaleAnimation scale = new ScaleAnimation(1.5f, 0.5f, 1.5f, 0.5f);
scale.setDuration(4000);
aniSet.addAnimation(scale);
// 位移动画
TranslateAnimation translate = new TranslateAnimation(0, 160, 0, 240);
translate.setDuration(4000);
aniSet.addAnimation(translate);
// 把动画设置给llGroup
llGroup.startAnimation(aniSet);
属性动画
简介
作用对象:任意Java对象(不再局限视图View对象)
实现的动画效果:可自定义各种动画效果(不再局限于4种基本变换)
原理
在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果。这里的可以是任意对象的任意属性。
可理解为一种按照一定变化率对属性值进行操作的机制,变化率就是依赖Interpolator控制,而值操作则是TypeEvaluator控制。
流程
ValueAnimator
ValueAnimator 类是先改变值,然后 手动赋值 给对象的属性从而实现动画;是 间接 对对象属性进行操作
1)ValueAnimator.ofInt (int value)
将初始值 以整型数值的形式 过渡到结束值,即估值器是整型估值器 - IntEvaluator
2)ValueAnimator.ofFloat (float value)
将初始值 以整型数值的形式 过渡到结束值,即估值器是浮点型估值器 - FloatEvaluator。
3)ValueAnimator.ofObject (onject value)
将初始值以对象的形式过渡到结束值,通过操作实现动画效果。 需要自定义估值器,没有默认的。
ObjectAnimator
ObjectAnimator 类是先改变值,然后 自动赋值 给对象的属性从而实现动画;是 直接 对对象属性进行操作;
ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String property, float …values);
//动画作用对象是mButton,属性是透明度alpha,效果是常规-全透明-常规
ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, “alpha”, 1f, 0f, 1f);
// ofFloat()作用有两个
// 1. 创建动画实例
// 2. 参数设置:参数说明如下
// Object object:需要操作的对象
// String property:需要操作的对象的属性传入alpha、rotation、translationX 和 scaleY设置改变的属性值
// float …values:动画初始值 & 结束值(不固定长度)
// 若是两个参数a,b,则动画效果则是从属性的a值到b值
// 若是三个参数a,b,c,则则动画效果则是从属性的a值到b值再到c值
// 以此类推
// 至于如何从初始值 过渡到 结束值,同样是由估值器决定,此处ObjectAnimator.ofFloat()是有系统内置的浮点型估值器FloatEvaluator,同ValueAnimator讲解
anim.setDuration(500);// 设置动画运行的时长
anim.setStartDelay(500);// 设置动画延迟播放时间
anim.setRepeatCount(0);// 设置动画重复播放次数 = 重放次数+1,动画播放次数 = infinite时,动画无限重复
anim.setRepeatMode(ValueAnimator.RESTART);// 设置重复播放动画模式:ValueAnimator.RESTART(默认):正序重放,ValueAnimator.REVERSE:倒序回放
animator.start(); // 启动动画
View动画与属性动画对比
视图动画优点:
- 当我们把动画的repeatCount设置为无限循环时,如果在Activity退出时没有及时将动画停止,属性动画会导致Activity无法释放而导致内存泄漏,而补间动画却没有问题。因此,使用属性动画时切记在Activity执行 onStop 方法时顺便将动画停止。
- xml 文件实现的补间动画,复用率极高。在Activity切换,窗口弹出时等情景中有着很好的效果。
视图动画缺点:
- 作用对象局限:View
即补间动画 只能够作用在视图View上,无法满足动画效果只是视图的某个属性时的实现。 - 没有改变View的属性,只改变视觉效果
补间动画只是改变了View的视觉效果,而不会真正去改变View的属性。如,将屏幕左上角的按钮 通过补间动画 移动到屏幕的右下角,点击当前按钮位置(屏幕右下角)是没有效果的 - 动画效果单一
补间动画只能实现平移、旋转、缩放 & 透明度这些简单的动画需求一旦遇到相对复杂的动画效果
属性动画优点:
- 作用对象是任何一个Object对象
我们完全可以给任意Object对象设置属性动画 - 实际改变了View对象的属性
会通过反射技术来获取和执行属性的get、set方法,从而改变了对象位置的属性值 - 可以控制动画执行过程中的任意时刻的任意属性值
自定义估值器控制动画执行过程中的属性值
插值器与估值器
插值器
设置 属性值 从初始值过渡到结束值 的变化规律,如匀速、加速 & 减速 等等,即确定了 动画效果变化的模式,如匀速变化、加速变化 等等
系统内置插值器
自定义插值器
自定义插值器需要实现 Interpolator / TimeInterpolator接口 & 复写getInterpolation(),补间动画 实现 Interpolator接口;属性动画实现TimeInterpolator接口。
//先减速再加速的插值器
public class DecelerateAccelerateInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
float result;
if (input <= 0.5) {
result = (float) (Math.sin(Math.PI * input)) / 2;
// 使用正弦函数来实现先减速后加速的功能,逻辑如下:
// 因为正弦函数初始弧度变化值非常大,刚好和余弦函数是相反的
// 随着弧度的增加,正弦函数的变化值也会逐渐变小,这样也就实现了减速的效果。
// 当弧度大于π/2之后,整个过程相反了过来,现在正弦函数的弧度变化值非常小,渐渐随着弧度继续增加,变化值越来越大,弧度到π时结束,这样从0过度到π,也就实现了先减速后加速的效果
} else {
result = (float) (2 - Math.sin(Math.PI * input)) / 2;
}
return result;
// 返回的result值 = 随着动画进度呈先减速后加速的变化趋势
}
}
估值器
设置属性值从初始值过渡到结束值的变化具体数值的一个接口,用于决定值的变化规律(如匀速、加速等),是属性动画特有的属性
系统内置估值器
自定义估值器
根据 插值器计算出当前属性值改变的百分比 & 初始值 & 结束值 来计算 当前属性具体的数值
自定义估值器需要实现 TypeEvaluator接口 & 复写evaluate()
PointEvaluator.java
// 实现TypeEvaluator接口
public class PointEvaluator implements TypeEvaluator {
// 复写evaluate()
// 在evaluate()里写入对象动画过渡的逻辑
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
// 将动画初始值startValue 和 动画结束值endValue 强制类型转换成Point对象
Point startPoint = (Point) startValue;
Point endPoint = (Point) endValue;
// 根据fraction来计算当前动画的x和y的值
float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
// 将计算后的坐标封装到一个新的Point对象中并返回
Point point = new Point(x, y);
return point;
}
}