Android中的动画之属性动画

212 阅读7分钟

Android中的动画之属性动画

属性动画

属性动画提供了两个类
    * ViewPropertyAnimator
    * ObjectAnimator
    
    区别:
        * ViewPropertyAnimator 只能操作他给我们提供的属性。而 ObjectAnimator 可以自己定制属性;
        * ViewPropertyAnimator 使用简单,而 ObjectAnimator 的使用并不简单;
        * 
    

ViewPropertyAnimator

使用方法

    // 获取 ViewPropertyAnimator 对象
    ViewPropertyAnimator anim = mImageView.animate();

    // 调用 ViewPropertyAnimator 方法
    anim.translationX(100);// 设置X轴的偏移 
    anim.translationY(100);// 设置Y轴的偏移 
    anim.translationZ(100);// 设置Z轴的偏移 
    anim.rotation(100); // 设置平面旋转 
    anim.rotationX(100);// 设置沿X轴旋转 
    anim.rotationY(100);// 设置沿Y轴旋转 
    anim.scaleX(100);// 设置横向缩放 
    anim.scaleY(100);// 设置纵向缩放 
    anim.alpha(1); // 设置透明度 
    anim.setInterpolator(new LinearInterpolator());// 设置速度模型 
    anim.setDuration(500);// 设置动画时间

  
链式调用:
    mImageView.animate()
        .translationX(100)// 设置X轴的偏移
        .translationY(100)// 设置Y轴的偏移
        .translationZ(100)// 设置Z轴的偏移
        .rotation(100) // 设置平面旋转
        .rotationX(100)// 设置沿X轴旋转
        .rotationY(100)// 设置沿Y轴旋转
        .scaleX(100)// 设置横向缩放
        .scaleY(100)// 设置纵向缩放
        .alpha(1)   // 设置透明度
        .setInterpolator(new AccelerateDecelerateInterpolator())// 设置速度模型
        .setDuration(500);// 设置动画时间

ObjectAnimator

构造方法
    * ObjectAnimator.ofFloat();// 创建属性值为float类型的对象
    * ObjectAnimator.ofInt();// 
    * ObjectAnimator.ofArgb();// 
    * ObjectAnimator.ofObject();// 
    * ObjectAnimator.ofMultiFloat();// 
    * ObjectAnimator.ofMultiInt();// 
    * ObjectAnimator.ofPropertyValuesHolder();// 

构造参数说明
    * ObjectAnimator anim = ObjectAnimator.ofFloat(目标view, 属性名, 目标值);
    * ObjectAnimator anim = ObjectAnimator.ofFloat(目标view, 属性名, 起始值, 目标值);
    * ObjectAnimator anim = ObjectAnimator.ofFloat(目标view, 属性名, 起始值, 转接值, 转接值, 目标值);

用法1
    // 第1步:获取对象
    ObjectAnimator anim = ObjectAnimator.ofXXX();
    // 第2步:开始执行动画
    anim.start(); 
    
用法2:自定义view
    // 第1步:给自定义view添加set()和get()方法;
    setProgress(float vlue){
        this.
    }// set()方法
    float getProgress();// get()方法
    // 第2步:获取对象
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "progress", 50);
    // 第3步:开始执行动画
    anim.start(); 
    
    
举例:让img向右平移400
ObjectAnimator anim = ObjectAnimator.ofFloat(mImageView, "translationX", 400);// 获取对象
anim.start();// 开始执行动画


举例:从一个颜色值变到另外一个颜色值
ObjectAnimator anim = ObjectAnimator.ofInt(mView, "color", 0xffff0000, 0xff00ff00);// 默认使用的是 IntEvaluator
anim.setEvaluator(new ArgbEvaluator());// 设置 Evaluator [知识拓展]
anim.start();// 开始执行动画


知识拓展:
Evaluator 的内容看这里:https://juejin.cn/post/7218916720332161082

属性动画 - 监听器

给动画设置监听器,可以在关键时刻得到反馈,从而及时做出合适的操作,例如在动画的属性更新时同步更新其他数据,或者在动画结束后回收资源等。

ViewPropertyAnimator 的监听器
    1.设置监听器:
        * setListener(AnimatorListener anim);
        * setUpdateListener(AnimatorUpdateListener anim);

    2.移除监听器:
        * setListener(null);
        * setUpdateListener(null);


ObjectAnimator 的监听器
    1.设置监听器:
        * addListener(AnimatorListener anim);
        * addUpdateListener(AnimatorUpdateListener anim);
    2.移除监听器:
        * removeListener();
        * removeUpdateListener();

注意:
1.由于 ObjectAnimator 支持使用 pause() 方法暂停,所以它还多了暂停监听的支持;
    * addPauseListener();
    * removePauseListener();
2.ViewPropertyAnimator 可以设置一次性的动画开始或结束的监听。
    * withStartAction();
    * withEndAction();


AnimatorListener 类介绍:共有 4 个回调方法
    1.onAnimationStart(Animator animation);// 当动画开始执行时,这个方法被调用。
    2.onAnimationEnd(Animator animation);// 当动画结束时,这个方法被调用。
    3.onAnimationCancel(Animator animation);// 当动画被通过 `cancel()` 方法取消时,这个方法被调用。
        * 需要说明一下的是,就算动画被取消,`onAnimationEnd()` 也会被调用。
        * 所以当动画被取消时,如果设置了 AnimatorListener ,那么 onAnimationCancel() 和 onAnimationEnd() 都会被调用。
        * onAnimationCancel() 会先于 onAnimationEnd() 被调用。
    4.onAnimationRepeat(Animator animation);// 当动画通过 `setRepeatMode()` / `setRepeatCount()` 或 `repeat()` 方法重复执行时,这个方法被调用。
        * 由于 `ViewPropertyAnimator` 不支持重复,所以这个方法对 `ViewPropertyAnimator` 相当于无效。


AnimatorUpdateListener 类介绍:就一个方法
    * onAnimationUpdate(ValueAnimator animation);// 当动画的属性更新时(不严谨的说,即每过 10 毫秒,动画的完成度更新时),这个方法被调用。
        * 方法的参数是一个 `ValueAnimator`,`ValueAnimator` 是 `ObjectAnimator` 的父类,也是 `ViewPropertyAnimator` 的内部实现,所以这个参数其实就是 `ViewPropertyAnimator` 内部的那个 `ValueAnimator`,或者对于 `ObjectAnimator` 来说就是它自己本身。
        * `ValueAnimator` 有很多方法可以用,它可以查看当前的动画完成度、当前的属性值等等。

插值器 Interpolator

系统提供的插值器:
    1.AccelerateDecelerateInterpolator();// 默认,先加速再减速(从速度为 0 开始逐渐加速,然后再逐渐减速直到 02.LinearInterpolator();// 匀速,线性
    3.AnticipateOvershootInterpolator();// 带施法前摇和回弹
    4.AccelerateInterpolator();// 持续加速(在整个动画过程中,一直在加速,直到动画结束的一瞬间,直接停止)
    5.DecelerateInterpolator();// 持续减速直到0(动画开始的时候是最高速度,然后在动画过程中逐渐减速,直到动画结束的时候恰好减速到 06.AnticipateInterpolator();// 先回拉一下再进行正常动画轨迹(蓄力效果)
    7.OvershootInterpolator();// 动画会超过目标值一些,然后再弹回来(效果看起来有点像你一屁股坐在沙发上后又被弹起来一点的感觉)
    8.AnticipateOvershootInterpolator();// 67的结合体(开始前回拉,最后超过一些然后回弹)
    9.BounceInterpolator();// 在目标值处弹跳(有点像玻璃球掉在地板上的效果)
    10.CycleInterpolator();// 这个也是一个正弦 / 余弦曲线,不过它和 `AccelerateDecelerateInterpolator` 的区别是,它可以自定义曲线的周期,所以动画可以不到终点就结束,也可以到达终点后回弹,回弹的次数由曲线的周期决定,曲线的周期由 `CycleInterpolator()` 构造方法的参数决定。
    11.PathInterpolator();// 自定义动画完成度 / 时间完成度曲线。用这个 "Interpolator" 你可以定制出任何你想要的速度模型。定制的方式是使用一个 "Path" 对象来绘制出你要的动画完成度 / 时间完成度曲线。

除了上面的这些,Android 5.0 (API 21)引入了三个新的 `Interpolator` 模型,并把它们加入了 support v4 包中。这三个新的 `Interpolator` 每个都和之前的某个已有的 `Interpolator` 规则相似,只有略微的区别。

Android5.0(API 21)引入的三个 "Interpolator" 模型:

    1.FastOutLinearInInterpolator();// 加速运动。
        * 这个 `Interpolator` 的作用你不能看它的名字,一会儿 fast 一会儿 linear 的,完全看不懂。
        * 其实它和 `AccelerateInterpolator` 一样,都是一个持续加速的运动路线。只不过 `FastOutLinearInInterpolator` 的曲线公式是用的贝塞尔曲线,而 `AccelerateInterpolator` 用的是指数曲线。
        * 具体来说,它俩最主要的区别是 `FastOutLinearInInterpolator` 的初始阶段加速度比 `AccelerateInterpolator` 要快一些。
    2.FastOutSlowInInterpolator();// 先加速再减速。
        * 同样也是先加速再减速的还有前面说过的 `AccelerateDecelerateInterpolator`,不过它们的效果是明显不一样的。
        * `FastOutSlowInInterpolator` 用的是贝塞尔曲线,`AccelerateDecelerateInterpolator` 用的是正弦 / 余弦曲线。
        * 具体来讲, `FastOutSlowInInterpolator` 的前期加速度要快得多。
    3.LinearOutSlowInInterpolator();// 持续减速。
        * 它和 `DecelerateInterpolator` 比起来,同为减速曲线,主要区别在于 `LinearOutSlowInInterpolator` 的初始速度更高。
        * 对于人眼的实际感觉,区别其实也不大,不过还是能看出来一些的。
  



---------------------------------------------------------------------------
------------------------- 插值器:PathInterpolator -------------------------
---------------------------------------------------------------------------

解释:
* 自定义动画完成度 / 时间完成度曲线。
* 用这个 "Interpolator" 你可以定制出任何你想要的速度模型。
* 定制的方式是使用一个 "Path" 对象来绘制出你要的动画完成度 / 时间完成度曲线。

例如:
案例1:匀速效果
    Path interpolatorPath = new Path();
    interpolatorPath.lineTo(1, 1);// 匀速

案例2:回弹效果
    Path interpolatorPath = new Path();
    // 先以「动画完成度 : 时间完成度 = 1 : 1」的速度匀速运行 25%
    interpolatorPath.lineTo(0.25f, 0.25f);
    // 然后瞬间跳跃到 150% 的动画完成度
    interpolatorPath.moveTo(0.25f, 1.5f);
    // 再匀速倒车,返回到目标点
    interpolatorPath.lineTo(1, 1);

注意:
你根据需求,绘制出自己需要的 `Path`,就能定制出你要的速度模型。

不过要注意,这条 `Path` 描述的其实是一个 `y = f(x) (0 ≤ x ≤ 1)` (y 为动画完成度,x 为时间完成度)的曲线,所以同一段时间完成度上不能有两段不同的动画完成度(这个好理解吧?因为内容不能出现分身术呀),而且每一个时间完成度的点上都必须要有对应的动画完成度(因为内容不能在某段时间段内消失呀)。所以,下面这样的 `Path` 是非法的,会导致程序 FC:

程序FC的几种情况:
    * 出现重复的动画完成度,即动画内容出现「分身」——程序 FC
    * 有一段时间完成度没有对应的动画完成度,即动画出现「中断」——程序 FC