属性动画详解

转载请注明链接:https://blog.csdn.net/feather_wch/article/details/79807024

属性动画详解

1、ViewPropertyAnimator是什么?由来和特点?

  • 属性动画提供的ValueAnimator类和ObjectAnimator类本质不是针对View对象而设计的,而是一种对数值不断操作的过程,但大部分情况下还是对View进行动画操作的。因此Google官方3.1中推出了ViewPropertyAnimator
    1. 专门针对View对象动画而操作的类。
    2. 提供了更简洁的链式调用设置多个属性动画,这些动画可以同时进行。
    3. 拥有更好的性能,多个属性动画是一次同时变化,只执行一次UI刷新(也就是只调用一次invalidate,而n个ObjectAnimator就会进行n次属性变化,就有n次invalidate)。
    4. 每个属性提供两种类型方法设置(直接设置和By的形式)。
    5. 该类只能通过View的animate()获取其实例对象的引用

2、ViewPropertyAnimator的使用方法

1-只能通过view.animate()方法实例化
2-view.animate().translationX(500);
ViewPropertyAnimator
3-图中大部分方法都具有xxxBy()版本,如view.animate().translationXBy(10);会在当前基础上+10

2、ObjectAnimator的使用步骤

  1. 如果是自定义控件,需要添加 setter / getter 方法;
  2. ObjectAnimator.ofXXX() 创建 ObjectAnimator 对象;
  3. 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()的使用

  1. 属性动画可以借助自定义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的作用

  1. 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. 把一个属性进行拆分
// 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、复杂属性动画大致三种方法

  1. 使用 PropertyValuesHolder 来对多个属性同时做动画;
  2. 使用 AnimatorSet 来同时管理调配多个动画;
  3. 使用 PropertyValuesHolder.ofKeyframe() 来把一个属性拆分成多段,执行更加精细的属性动画。

17、ValueAnimator

  1. ObjectAnimator的父类
  2. 在做属性动画却没有getter和setter时使用
  3. ValueAnimator只通过渐变方法去改变数值,而具体操作由我们决定。
  4. 第三方控件做动画就可以用ValueAnimator并且在opUpdate()来更新这个属性值,并手动调用invalidate()

猜你喜欢

转载自blog.csdn.net/feather_wch/article/details/79807024