概述:本篇文章只对自定义View可能用到的 Property Animation(属性动画)进行讲解。以后的博客中会有一篇文章对Android中的动画进行全面的归纳讲解。

一 Property Animation 简介

Property Animation 又被称为属性动画,通过不断的改变View的属性形成的动画。分类两个大类:1 ViewPropertyAnimator ,2 ObjectAnimator

1 ViewPropertyAnimator

使用方式:View.animate() 后跟 translationX() 等方法,动画会自动执行
view.animate().translationX(500);  view向右移动500像素的位置
一张来自HenCoder的图片

android 动态改变view坐标 android 属性动画改变view大小_回弹

从图中可以看到, View 的每个方法都对应了 ViewPropertyAnimator 的两个方法,其中一个是带有 -By 后缀的,例如,View.setTranslationX() 对应了 ViewPropertyAnimator.translationX() 和 ViewPropertyAnimator.translationXBy() 这两个方法。其中带有 -By() 后缀的是增量版本的方法,例如,translationX(100) 表示用动画把 View 的 translationX 值渐变为 100,而 translationXBy(100) 则表示用动画把 View 的 translationX 值渐变地增加 100。

2 ObjectAnimator

使用方式:
1 如果是自定义控件,需要添加 setter / getter 方法;
2 用 ObjectAnimator.ofXXX() 创建 ObjectAnimator 对象
3 用 start() 方法执行动画
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", 0, 65);
animator.start();
参数 view是需要执行动画的目标, “translationX”是通过匹配对应的setter方法,执行的动画。例如这里,匹配对应的setTranslationX()方法。执行平移动画。0,65 表示属性值从 0 改变到 65。

二 Property Animation 通用的方法

1. setDuration(int duration) 设置动画时长

ViewPropertyAnimator的方式:
imageView1.animate()  
        .translationX(500)
        .setDuration(500);

ObjectAnimator的设置方式:
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView2, "translationX", 500);
animator.setDuration(2000);  
animator.start();

2. setInterpolator(Interpolator interpolator) 设置 Interpolator(插值器)

ViewPropertyAnimator的方式:
imageView1.animate()  
        .translationX(500)
        .setDuration(500)
        .setInterpolator(new LinearInterpolator());

ObjectAnimator的设置方式:
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView2, "translationX", 500);
animator.setDuration(2000);  
animator.setInterpolator(new LinearInterpolator());
animator.start();

Interpolator 其实就是速度设置器。你在参数里填入不同的 Interpolator ,动画就会以不同的速度模型来执行。一下是插值器简介:

1 AccelerateDecelerateInterpolator 默认插值器,最符合现实的物理模型。先加速再减速
2 LinearInterpolator 线性插值器,匀速。
3 AccelerateInterpolator 持续加速 在整个动画过程中,一直在加速,直到动画结束的一瞬间,直接停止。它主要用在离场效果中,比如某个物体从界面中飞离,就可以用这种效果
4 DecelerateInterpolator 动画开始的时候是最高速度,然后在动画过程中逐渐减速,直到动画结束的时候恰好减速到 0。适用场景也和它相反:它主要用于入场效果,比如某个物体从界面的外部飞入界面后停在某处
5 AnticipateInterpolator 先回拉一下再进行正常动画轨迹。效果看起来有点像投掷物体或跳跃等动作前的蓄力
6 OvershootInterpolator 动画会超过目标值一些,然后再弹回来。效果看起来有点像你一屁股坐在沙发上后又被弹起来一点的感觉。
7 AnticipateOvershootInterpolator 上面这两个的结合版:开始前回拉,最后超过一些然后回弹
8 BounceInterpolator 在目标值处弹跳。有点像玻璃球掉在地板上的效果。
9 CycleInterpolator 这个也是一个正弦 / 余弦曲线,不过它和 AccelerateDecelerateInterpolator 的区别是,它可以自定义曲线的周期,所以动画可以不到终点就结束,也可以到达终点后回弹,回弹的次数由曲线的周期决定,曲线的周期由 CycleInterpolator() 构造方法的参数决定。
10 PathInterpolator 自定义动画完成度 / 时间完成度曲线。用这个 Interpolator 你可以定制出任何你想要的速度模型。定制的方式是使用一个 Path 对象来绘制出你要的动画完成度 / 时间完成度曲线 你根据需求,绘制出自己需要的 Path,就能定制出你要的速度模型
Path interpolatorPath = new Path();
interpolatorPath.lineTo(1, 1); // 匀速
11 FastOutLinearInInterpolator 加速运动。 FastOutLinearInInterpolator 的曲线公式是用的贝塞尔曲线,而 AccelerateInterpolator 用的是指数曲线。具体来说,它俩最主要的区别是 FastOutLinearInInterpolator 的初始阶段加速度比 AccelerateInterpolator 要快一些
12 FastOutSlowInInterpolator 先加速再减速 同样也是先加速再减速的还有前面说过的 AccelerateDecelerateInterpolator,不过它们的效果是明显不一样的。FastOutSlowInInterpolator 用的是贝塞尔曲线,AccelerateDecelerateInterpolator 用的是正弦 / 余弦曲线。具体来讲, FastOutSlowInInterpolator 的前期加速度要快得多。
13 LinearOutSlowInInterpolator 它和 DecelerateInterpolator 比起来,同为减速曲线,主要区别在于 LinearOutSlowInInterpolator 的初始速度更高。对于人眼的实际感觉,区别其实也不大,不过还是能看出来一些的

3. 设置动画监听器

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

1 ViewPropertyAnimator

设置监听: ViewPropertyAnimator.setListener()
       textView.animate().setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {
                // 当动画开始执行时,这个方法被调用。
            }

            @Override
            public void onAnimationEnd(Animator animator) {
                // 当动画结束执行时,这个方法被调用。
            }

            @Override
            public void onAnimationCancel(Animator animator) {
                // 当动画取消执行时,这个方法被调用。
            }

            @Override
            public void onAnimationRepeat(Animator animator) {
                // 这个方法对 ViewPropertyAnimator 无效  
            }

        });

更新监听: ViewPropertyAnimator.setUpdateListener()
       textView.animate().setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                // 动画更新 也就是执行过程中被调用
            }

ViewPropertyAnimator.withStartAction/EndAction()

这两个方法是 ViewPropertyAnimator 的独有方法。它们和 set/addListener() 中回调的 onAnimationStart() / onAnimationEnd() 相比起来的不同主要有两点:

1 withStartAction()是一次性的,在动画执行结束后就自动弃掉了,就算之后再重用  ViewPropertyAnimator 来做别的动画,用它们设置的回调也不会再被调用。而 set/addListener() 所设置的 AnimatorListener 是持续有效的,当动画重复执行时,回调总会被调用
2 withEndAction() 设置的回调只有在动画正常结束时才会被调用,而在动画被取消时不会被执行。这点和AnimatorListener.onAnimationEnd() 的行为是不一致的。

2 ObjectAnimator

设置监听: ObjectAnimator.addListener()
        ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "translationX", 180);
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {
                // 当动画开始执行时,这个方法被调用。
            }

            @Override
            public void onAnimationEnd(Animator animator) {
                // 当动画结束执行时,这个方法被调用。
            }

            @Override
            public void onAnimationCancel(Animator animator) {
                // 当动画取消执行时,这个方法被调用。
                // onAnimationEnd() 也会被调用。所以当动画被取消时,如果设置了  AnimatorListener,那么 onAnimationCancel() 和 onAnimationEnd() 都会被调用。onAnimationCancel() 会先于 onAnimationEnd() 被调用。
            }

            @Override
            public void onAnimationRepeat(Animator animator) {
                //当动画通过 setRepeatMode() / setRepeatCount() 或 repeat() 方法重复执行时,这个方法被调用
            }
        });
更新监听: ObjectAnimator.addUpdateListener()
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                // 当动画的属性更新时(不严谨的说,即每过 10 毫秒,动画的完成度更新时),这个方法被调用
            }
        });
停止监听:ObjectAnimator.addPauseListener()