转载请注明链接:https://blog.csdn.net/feather_wch/article/details/79807024
属性动画详解
1、ViewPropertyAnimator是什么?由来和特点?
属性动画
提供的ValueAnimator类和ObjectAnimator类
本质不是针对View对象
而设计的,而是一种对数值不断操作
的过程,但大部分情况下还是对View
进行动画操作的。因此Google官方
在3.1
中推出了ViewPropertyAnimator
。
- 专门针对View对象动画而操作的类。
- 提供了更简洁的
链式调用
设置多个属性动画,这些动画可以同时进行。拥有更好的性能
,多个属性动画是一次同时变化,只执行一次UI刷新(也就是只调用一次invalidate,而n个ObjectAnimator就会进行n次属性变化,就有n次invalidate)。- 每个属性提供
两种类型方法
设置(直接设置和By
的形式)。- 该类只能通过
View的animate()
获取其实例对象的引用
2、ViewPropertyAnimator的使用方法
1-只能通过
view.animate()方法
实例化
2-view.animate().translationX(500);
3-图中大部分方法
都具有xxxBy()
版本,如view.animate().translationXBy(10);
会在当前基础上+10
2、ObjectAnimator的使用步骤
- 如果是自定义控件,需要添加
setter / getter
方法;- 用
ObjectAnimator.ofXXX()
创建 ObjectAnimator 对象;- 用
start()
方法执行动画。
public class SportsView extends View {
float progress = 0;
// 创建 getter 方法
public float getProgress() {
return progress;
}
// 创建 setter 方法
public void setProgress(float progress) {
this.progress = progress;
invalidate();
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(arcRectF, 135, progress * 2.7f, false, paint);
}
}
// 创建 ObjectAnimator 对象
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "progress", 0, 65);
// 执行动画
animator.start();
3、ObjectAnimator的通用方法
setDuration(int duration) //设置动画时长-单位是毫秒。
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView2, "translationX", 500);
//1. 设置动画时长,单位毫秒。
animator.setDuration(2000);
//2. 设置插值器(动画的速度和表现形式)
animator.setInterpolator(new AccelerateDecelerateInterpolator()); //先加速,再减速。
animator.setInterpolator(new LinearInterpolator()); //匀速
animator.setInterpolator(new AccelerateInterpolator()); //加速
animator.setInterpolator(new DecelerateInterpolator()); //减速
animator.setInterpolator(new AnticipateInterpolator()); //先回拉再进行正常动画(如放大的会先缩小在放大)
animator.setInterpolator(new OvershootInterpolator()); //会超过目标值,然后回到目标值。
animator.setInterpolator(new AnticipateOvershootInterpolator()); //先回拉,正常动画,会超过目标值然后反弹到目标值。
animator.setInterpolator(new BounceInterpolator()); //目标处弹动
animator.setInterpolator(new CycleInterpolator(0.5f)); //一个正弦/余弦曲线,可以自定义曲线的周期,动画可以不到终点就结束,可以到达终点后回弹。
/**
* 自定义动画完成度 / 时间完成度曲线。
* 1. path-必须连续不能间断,也不能重叠
* https://ws4.sinaimg.cn/large/006tKfTcly1fj8jmom7kaj30cd0ay74f.jpg
* */
Path interpolatorPath = new Path();
// 先以「动画完成度 : 时间完成度 = 1 : 1」的速度匀速运行 25%
interpolatorPath.lineTo(0.25f, 0.25f);
// 然后瞬间跳跃到 150% 的动画完成度
interpolatorPath.moveTo(0.25f, 1.5f);
// 再匀速倒车,返回到目标点
interpolatorPath.lineTo(1, 1);
animator.setInterpolator(new PathInterpolator(interpolatorPath));
animator.setInterpolator(new FastOutLinearInInterpolator()); //加速运动(贝塞尔曲线)
animator.setInterpolator(new FastOutSlowInInterpolator()); //先加速再减速
animator.setInterpolator(new LinearOutSlowInInterpolator()); //持续减速
animator.start();
4、ViewPropertyAnimator/ObjectAnimator设置AnimatorListener监听器
//1-设置方法
view.animate().setListener(xxx);
objectAnimator.addListener(xxx);
//2-监听器的回调
new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
//动画开始执行时调用
}
@Override
public void onAnimationEnd(Animator animation) {
//动画结束时调用
}
@Override
public void onAnimationCancel(Animator animation) {
//1-动画通过cancel取消时,调用
//2-cancel()之后onAnimationEnd()依旧会调用
}
@Override
public void onAnimationRepeat(Animator animation) {
//ViewPropertyAnimator不支持重复,因此该方法无效
//ObjectAnimator通过setRepeatMode()和setRepeatCount()或者repeat()重复执行时,会调用
}
}
5、ViewPropertyAnimator/ObjectAnimator设置AnimatorUpdateListener
//1-设置更新监听器
objectAnimator.addUpdateListener(xxx);
view.animate().setUpdateListener(xxx);
//2-回调方法
new ValueAnimator.AnimatorUpdateListener(){
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//1-当动画的属性更新时,就会调用
//2-参数的ValueAnimator是ObjectAnimator的父类,也是ViewPropertyAnimator的内部实现
//3-ValueAnimator具有很多方法(查看当前的动画完成度、当前属性等)
}
}
6、ObjectAnimator的addPauseListener()方法
```
7、 ViewPropertyAnimator.withStartAction/EndAction()
>这两个方法是 ViewPropertyAnimator 的独有方法。它们和 set/addListener() 中回调的 onAnimationStart() / onAnimationEnd() 相比起来的不同主要有两点:
> * withStartAction() / withEndAction() 是一次性的,在动画执行结束后会自动弃掉,之后再重用 ViewPropertyAnimator 来做别的动画,用它们设置的回调也不会再被调用。而 set/addListener() 所设置的 AnimatorListener 是持续有效的,当动画重复执行时,回调总会被调用。
> * withEndAction() 设置的回调只有在动画正常结束时才会被调用,而在动画被取消时不会被执行。这点和 AnimatorListener.onAnimationEnd() 的行为不一致。
8、估值器(TypeEvaluator)是什么?
>1. `ObjectAnimator`可以用`ofInt`做整数的属性动画,`ofFloat`做浮点数的属性动画。
>2. `其他类型的属性`就需要`TypeEvaluator`做属性动画。
9、ArgbEvaluator颜色估值器
```java
//1、颜色的渐变
animator = ObjectAnimator.ofInt(this, "color", 0xffff0000, 0xff00ff00);
animator.setEvaluator(new ArgbEvaluator());
//2、颜色渐变(API >= 21)
animator = ObjectAnimator.ofArgb(this, "color", 0xffff0000, 0xff00ff00);
animator.start();
<div class="se-preview-section-delimiter"></div>
10、自定义颜色Evaluator
private class HsvEvaluator implements TypeEvaluator<Integer> {
float[] startHsv = new float[3];
float[] endHsv = new float[3];
float[] outHsv = new float[3];
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
// 把 ARGB 转换成 HSV
Color.colorToHSV(startValue, startHsv);
Color.colorToHSV(endValue, endHsv);
// 计算当前动画完成度(fraction)所对应的颜色值
if (endHsv[0] - startHsv[0] > 180) {
endHsv[0] -= 360;
} else if (endHsv[0] - startHsv[0] < -180) {
endHsv[0] += 360;
}
outHsv[0] = startHsv[0] + (endHsv[0] - startHsv[0]) * fraction;
if (outHsv[0] > 360) {
outHsv[0] -= 360;
} else if (outHsv[0] < 0) {
outHsv[0] += 360;
}
outHsv[1] = startHsv[1] + (endHsv[1] - startHsv[1]) * fraction;
outHsv[2] = startHsv[2] + (endHsv[2] - startHsv[2]) * fraction;
// 计算当前动画完成度(fraction)所对应的透明度
//右移动24位, ARGB 一共32位,每8位代表一个属性,依次代表透明度(alpha)、红色(red)、绿色(green)、蓝色(blue)。
int alpha = startValue >> 24 + (int) ((endValue >> 24 - startValue >> 24) * fraction);
// 把 HSV 转换回 ARGB 返回
return Color.HSVToColor(alpha, outHsv);
}
}
//使用一:
ObjectAnimator animator = ObjectAnimator.ofInt(view, "color", 0xffff0000, 0xff00ff00);
// 使用二:
ObjectAnimator animator = ObjectAnimator.ofObject(view, "color",
new HsvEvaluator(), 0xffff0000, 0xff00ff00);
// 使用自定义的 HslEvaluator
animator.setEvaluator(new HsvEvaluator());
animator.start();
<div class="se-preview-section-delimiter"></div>
1、HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。
1. 色调H
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
2. 饱和度S
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
3. 明度V
明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
4、PropertyValuesHolders.ofKeyframe()讲的不是很细致,下面文章讲的很不错,可以借鉴引用一下。
以上是本人的建议,望大佬能见谅。
http://blog.csdn.net/xuefu_78/article/details/52415673
11、ofObject()的使用
属性动画
可以借助自定义TypeEvaluator
通过ofObject()
来对不限定类的属性做动画
//API21中已经实现,理解思路
private class PointFEvaluator implements TypeEvaluator<PointF> {
PointF newPoint = new PointF();
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
float x = startValue.x + (fraction * (endValue.x - startValue.x));
float y = startValue.y + (fraction * (endValue.y - startValue.y));
newPoint.set(x, y);
return newPoint;
}
}
ObjectAnimator animator = ObjectAnimator.ofObject(view, "position",
new PointFEvaluator(), new PointF(0, 0), new PointF(1, 1));
animator.start();
<div class="se-preview-section-delimiter"></div>
12、新API中新增了ofMultiInt()、ofMultiFloat()等方法
13、PropertyValueHolder的作用
ViewPropertyAnimator
中通过链式调用
就可以同时改变多个属性
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 1);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY", 1);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("alpha", 1);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, holder1, holder2, holder3)
animator.start();
<div class="se-preview-section-delimiter"></div>
14、AnimatorSet多个动画配合执行
ObjectAnimator animator1 = ObjectAnimator.ofFloat(...);
animator1.setInterpolator(new LinearInterpolator());
ObjectAnimator animator2 = ObjectAnimator.ofInt(...);
animator2.setInterpolator(new DecelerateInterpolator());
AnimatorSet animatorSet = new AnimatorSet();
// 1-两个动画依次执行
animatorSet.playSequentially(animator1, animator2);
animatorSet.start();
// 2-两个动画同时执行
animatorSet.playTogether(animator1, animator2);
animatorSet.start();
<div class="se-preview-section-delimiter"></div>
15、PropertyValuesHolders.ofKeyframe()
- 把一个属性进行
拆分
// 1、在 0% 处开始
Keyframe keyframe1 = Keyframe.ofFloat(0, 0);
// 2、时间经过 50% 的时候,动画完成度 100%
Keyframe keyframe2 = Keyframe.ofFloat(0.5f, 100);
// 3、时间见过 100% 的时候,动画完成度倒退到 80%,即反弹 20%
Keyframe keyframe3 = Keyframe.ofFloat(1, 80);
// 4、合成
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("progress", keyframe1, keyframe2, keyframe3);
// 5、使用
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, holder);
animator.start();
16、复杂属性动画大致三种方法
- 使用
PropertyValuesHolder
来对多个属性同时做动画;- 使用
AnimatorSet
来同时管理调配多个动画;- 使用
PropertyValuesHolder.ofKeyframe()
来把一个属性拆分成多段,执行更加精细的属性动画。
17、ValueAnimator
- 是
ObjectAnimator
的父类- 在做
属性动画
却没有getter和setter
时使用ValueAnimator
只通过渐变方法
去改变数值,而具体操作
由我们决定。- 给
第三方控件
做动画就可以用ValueAnimator
并且在opUpdate()
来更新这个属性值,并手动调用invalidate()