Android 动画之属性动画 - 基本使用

Android动画系列:

  • 补间动画详解
  • 帧动画
  • LayoutAnimation
  • LayoutTransition
  • 属性动画 - 基本使用
  • 属性动画 - Interpolator(内插器)
  • 属性动画 - TypeEvaluator
  • 属性动画 - Keyframe
  • AnimatorSet

介绍

在Android之补间动画详解已经了解到,View Animation通过重绘View的视图的方式来完成View的动画效果,但View对象本身没有改变。在Android 3.0(API 11),对View添加了新属性和相应的get()和set(),通过在调用set方法设置属性时,其属性更改时会自动调用invalidate()方法来刷新屏幕。

view用拥有set()方法的属性列表:

属性 描述
translationX / translationY/ translationZ 这两个属性控制了View所处的位置,它们的值是由layout容器设置的,是相对于坐标原点(0,0左上角)的一个偏移量。translationX和 translationY表示水平方向,translationZ为垂直方向(API 21新添加)
rotation,rotationX和rotationY 控制View绕着轴点(pivotX和pivotY)旋转
scaleX和scaleY 控制View基于pivotX和pivotY的缩放。
pivotX和pivotY 旋转的轴点和缩放的基准点,默认是View的中心点
x / y / Z 用于在其容器中描述视图的最终位置,作为左值和顶值以及translationX和translationY值的和。z为view的高度属性
alpha 表示view的透明度。默认情况下,此值为1(不透明),值为0表示完全透明(不可见)

属性动画可以通过更改View的属性,重绘View,更改属性后自动调用invalidate()方法来刷新屏幕,以完成动画效果。

动画特征

  1. Duration:动画执行时间,默认时间为300 ms
  2. TimeInterpolator :时间插值,用于计算指定属性的值在当前动画的执行时间
  3. Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始,还是反向。
  4. Animator Sets:动画集合,可以定义一起播放或顺序播放或在指定延迟后播放,
  5. Frame refresh delay:帧刷新延迟,对于定义的动画,多久刷新一次帧;默认为10ms,但最终依赖系统的当前状态及系统底层定时器所提供的服务。

相关类

  1. ValueAnimator:值动画执行类,常配合AnimatorUpdateListener使用
  2. ObjectAnimator:对象动画执行类。
  3. TimeInterpolator:定义动画插值器
  4. TypeEvaluator:类型估值,用于设置复杂的动画操作属性的值
  5. PropertyValuesHolder : 属性存储器,为两个执行类提供更新多个属性的功能
  6. Keyframe :为 PropertyValuesHolder提供多个关键帧的操作值
  7. AnimatorSet :一组动画的执行集合类:设置执行的先后顺序,时间等
  8. AnimatorUpdateListener :动画更新监听
  9. AnimatorListener :动画执行监听,在动画开始、重复、结束、取消时进行回调。
  10. AnimatorInflater :加载属性动画的xml文件。

常见的插值器

Interpolator对象 资源ID 功能作用
AccelerateDecelerateInterpolator @android:animaccelerate_decelerate_interpolator 先加速再减速
AccelerateInterpolator @android:anim/accelerate_interpolator 加速
AnticipateInterpolator @android:anim/anticipate_interpolator 先回退一小步然后加速前进
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 在上一个基础上超出终点一小步再回到终点
BounceInterpolator @android:anim/bounce_interpolator 最后阶段弹球效果
CycleInterpolator @android:anim/cycle_interpolator 周期运动
LinearInterpolator @android:anim/linear_interpolator 匀速运动

ValueAnimator

常量

  1. INFINITE:此值用于setRepeatCount(int)属性,用于无限期地重复动画。实际上其值等于-1,在XML中定义动画无限重复时,通常设置android:repeatCount=”-1”,也就是这样了
  2. RESTART:当动画设置为无限重复或者执行次数大于1时,动画执行结束后,从头开始
  3. REVERSE:当动画设置为无限重复或者执行次数大于1时,动画执行结束后,动画反向执行

常用API

返回值 方法 注解
void addUpdateListener(ValueAnimator.AnimatorUpdateListener) 添加动画更新监听
void cancel() 取消当前执行的动画
void end() 结束当前动画
void pause() 暂停动画
void reverse() 反向执行动画
void start() 开始动画
void resume() 恢复暂停的动画,从暂停的位置开始动画
float getAnimatedFraction() 获取当前动画的执行进度
Object getAnimatedValue() 获取当前属性值
Object getAnimatedValue(String) 通过属性标签获取属性的当前值
boolean isRunning() 判断动画是否在执行(动画已开始且运行时间超过所设置的延迟时间,但动画未结束)
boolean isStarted() 判断动画是否已经开始而且动画未结束
static ValueAnimator ofArgb(int… values) 设置颜色值之间切换的动画(比如设置背景颜色)
static ValueAnimator ofFloat(float… values) 设置在浮点值之间的动画(比如移动)
static ValueAnimator ofInt(int… values) 设置在整数值之间的动画
static ValueAnimator ofObject(TypeEvaluator evaluator, Object… values)) 在values值之间的动画
static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder… values) 设置在PropertyValuesHolders之间执行动画

注:

1.getAnimatedValue()和getAnimatedFraction()的区别

getAnimatedValue()的返回值是一个Object,表示当仅有一个属性处于动画状态时,由该ValueAnimator计算的当前属性值。

getAnimatedFraction()的返回值是一个float,其值在0.0和1.0之间,其线性度是由插值器决定的(fraction = t / duration ),而animatedValue值是由相关属性值 * fraction所得的。

2.ValueAnimator的构造函数其实就是一个默认构造函数,并包含动画相关”属性”信息,若采用此种方式创建实例,需通过调用setXX(…)方法设置动画相关属性。当然此时你可以通过静态方法创建ValueAnimator实例,比如ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f),此ValueAnimator设置了相关的动画”属性”

public class ValueAnimator() {
    ***
    public ValueAnimator() {
    }
    ***
}

Evaluators

类(接口) 描述
IntEvaluator 用于计算int属性的值的默认计算器
FloatEvaluator 用于计算float属性的值的默认计算器
ArgbEvaluator 用于计算表示为十六进制值的颜色属性值的默认计算器
TypeEvaluator 用于自定义属性值的计算器

3.动画的执行动作解析

  • cancel():取消当前执行的动画,将属性值分配成动画的当前值,调用cancel()方法后,会先触发AnimatorListener的onAnimationCancel方法的执行,然后触发onAnimationEnd方法的执行。
  • end():结束当前动画,直接从当前状态跳转到最终的完成状态,将属性值分配成动画的终止值,并触发动画监听器AnimatorListener的onAnimationEnd方法的执行。
  • pause():暂停当前执行的动画,将属性值分配成动画的当前值。(API > 19)
  • reverse():反向执行动画,但其执行动画的位置为动画的当前位置。但,若动画停留在起始位置,动画将从最后一帧开始;若动画停留在最后一帧,动画将从第一帧开始执行动画。
  • start():从第一帧开始执行动画。若设置了动画延迟,动画不会立即执行,待延迟时间过后,动画再执行;若未设置动画延迟,动画会立即执行
  • resume():恢复暂停的动画,从暂停的位置开始动画(API > 19)

动画实例

ofFloat/ofInt

ofFloat(float…)方法接收一系列的float类型的值,其内部使用了FloatEvaluator。通过该方法ValueAnimator可以对float值进行动画渐变。现通过ValueAnimator.ofFloat(0.0f, 400f);创建了一个初始值为0.0f,结束值为400f的动画。通过addUpdateListener(ValueAnimator.AnimatorUpdateListener)添加动画监听,AnimatorUpdateListener有一个onAnimationUpdate方法,ValueAnimator会每隔一定时间(默认间隔10ms)计算属性的值,每当计算的时候就会回调onAnimationUpdate方法。在该方法中,我们通过调用ValueAnimator的getAnimatedValue()方法获取到当前动画计算出的属性值,然后我们将该值传入btnProperty的setTranslationX()、setTranslationY()方法中,从而更新了btnProperty的位置,以达到了移动btnProperty的目的。

    // 通过静态方法构建一个ValueAnimator对象
    // 设置数值集合
    mValueAnimator = ValueAnimator.ofFloat(0.0f, 400f);
    // 设置作用对象
    mValueAnimator.setTarget(btnProperty);
    // 设置动画无限循环
    mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    // 设置动画执行时间
    mValueAnimator.setDuration(4000);
    // 添加动画更新监听
    mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            // 获取当前值
            Float mValue = (Float)animation.getAnimatedValue();
            // 动画进度(t/duration)
            float fraction = animation.getAnimatedFraction();

            Log.d("PropertyActivity", "mValue:" + mValue);
            Log.d("PropertyActivity", "fraction:" + fraction + " | t:" + fraction * animation.getDuration());

            // 设置横向偏移量
            btnProperty.setTranslationX(mValue * 0.5f);
            // 设置纵向偏移量
            btnProperty.setTranslationY(mValue);
        }
    });
    // 开始执行动画
    mValueAnimator.start();

Android 动画之属性动画 - 基本使用_第1张图片

ofInt(Int…)的使用方法与ofFloat()类似,这个可以自行解决,练练手~

ofArgb

此方法要求最低SDK 版本为21,是新添的方法,用于构造颜色值变化的动画。其内部使用了ArgbEvaluator,可以用该方法实现将一个颜色动画渐变到另一个颜色,我们从中可以不断获取中间动画产生的颜色值。我们知道一个int值包含四个字节,在Android中第一个字节代表Alpha分量,第二个字节代表Red分量,第三个字节代表Green分量,第四个字节代表Blue分量,且我们常用16进制表示颜色,这样看起来更明显易懂一些,比如int值0xffff0000表示的红色,0xff00ff00表示的是绿色,最前面的ff表示的是Alpha。ofArgb方法会通过ArgbEvaluator将颜色拆分成四个分量,然后分别对各个分量进行动画计算,然后将四个计算完的分量再重新组合成一个表示颜色的int值,这就是ofArgb方法的工作原理。

现通过静态方法ofArgb(Int…args)创建ValueAnimator对象,设置动画的执行时间为4000ms,设置动画的循环次数为无限循环。在AnimatorUpdateListener监听中,将ArgbEvaluator计算出的颜色的值,通过setBackgroundColor(int)传给btn,设置btn的背景颜色。

    //起始颜色为红色
    int startColor = 0xffff0000;
    //终止颜色为绿色
    int endColor = 0xff00ff00;

    // 通过静态方法构建一个ValueAnimator对象
    // 设置数值集合
    mValueAnimator = ValueAnimator.ofArgb(startColor, endColor);
    // 设置作用对象
    mValueAnimator.setTarget(btnProperty);
    // 设置动画无限循环
    mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    // 设置动画执行时间
    mValueAnimator.setDuration(4000);
    // 添加动画更新监听
    mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int valueColor = (int) animation.getAnimatedValue();
            Log.d("PropertyActivity", "mValue:" + valueColor);
            btnProperty.setBackgroundColor(valueColor);
        }
    });

Android 动画之属性动画 - 基本使用_第2张图片

ofObject

ofObject(TypeEvaluator, Object… values)与ofInt()、ofFloat()并不相同,其不仅有动画属性值作为参数,同时必须传入动画的属性计算器。一方面,由于ofObject()传入的属性值类型不能够确定,从而不能够确定哪种类型的属性值计算器。另一方面,官方提供的动画属性值就那么几种,并不能够满足我们实际的需求,假如传入了一个自定义类或者一系列的String属性值,官方提供的动画属性就不能满足了。而ofInt()、ofFloat()中动画的属性值类型固定,在其内分别内置了IntEvaluaor、FloatEvaluator。既然是这样,不管是使用官方提供的Evaluator还是Valuator都必须指定TypeEvaluator。

具体实例不在写出,详见

ObjectAnimator

介绍

ObjectAnimator是ValueAnimator的子类,不同于ValueAnimator的是,其内置了属性值计算器以及拥有对View的命名属性(拥有getter()和setter()的属性)。此时,不必在添加ValueAnimator.AnimatorUpdateListener,ObjectAnimator会自动设置View的属性并自动更新。

实例化的ObjectAnimator类似于ValueAnimator,可以指定对象、对象属性的名称及属性值之间的动画。

ObjectAnimator anim = ObjectAnimator.ofFloat(btn, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();

局限性

由于ObjectAnimator只能自动更新View的命名属性,有一定的局限性。使用ObjectAnimator时应注意:

  1. ObjectAnimator在动画期间自动更新属性,其必须能够调用setter()方法,因而View的动画属性必须有setter()方法。例如当设置View的背景色时,其不是命名属性,此时你只能

    • 自定义View,将此属性设置为命名属性
    • 改用ValueAnimator,添加AnimatorUpdateListener监听,在回调方法内设置View属性
  2. ObjectAnimator的属性值参数有且仅有一个,假定此值为结束值,该View必须有getter()方法,以用来获取初始值,而且getter()方法必须是get()的形式。

  3. 动画的属性的getter()和setter()方法中,propertyName的类型必须与ObjectAnimator指定的开始值和结束值的类型一致。

代码实例

ObjectAnimator//  
     .ofFloat(view, "rotationX", 0.0F, 360.0F)//  
     .setDuration(500)//  
     .start();  

动画监听

AnimatorUpdateListener

AnimatorUpdateListener是ValueAnimator类的一个成员内部类,其是静态的,且仅声明了一个方法onAnimationUpdate(ValueAnimator)。在动画执行过程中,每次更新都会调用该方法,可以在该回调中手动更新view的属性。

public class ValueAnimator{

    *** 

     public static interface AnimatorUpdateListener {

        void onAnimationUpdate(ValueAnimator animation);

    }

    ****
}

注:动画执行时,ValueAnimator会计算相关动画且执行动画,但其并不会设置view的属性和对view进行重绘。此时需设置AnimatorUpdateListener监听,并在onAnimationUpdate回调中执行View的invalidate()方法。

Animator.AnimatorListener

对于动画执行过程中,在动画执行过程中,我们总是想执行这样那样的操作,比如在动画结束时,不再显示当前框架,此时我们就得对整个动画的执行进行监听,了解当前动画的执行进度。如果想监听动画,需调用addListener(listener)添加Animator.AnimatorListener。

Animator.AnimatorListener内声明的监听回调方法:

  • onAnimationStart(Animator animation):动画开始时回调
  • onAnimationCancel(Animator animation):调用cancel()方法手动取消动画时回调
  • onAnimationEnd(Animator animation):调用end()方法手动结束动画或者动画正常结束时回调
  • onAnimationRepeat(Animator animation):动画重复时回调

    ValueAnimator mValueAnimator = ValueAnimator.ofFloat(0f, 400f);
    // 设置作用对象
    mValueAnimator.setTarget(btnProperty);
    // 设置动画无限循环
    mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    // 设置动画执行时间
    mValueAnimator.setDuration(4000);
    mValueAnimator.addListener(new Animator.AnimatorListener() {
    
        public void onAnimationStart(Animator animation) {
            Log.d("PropertyActivity", "动画开始");
        }
    
        @Override
        public void onAnimationEnd(Animator animation) {
            Log.d("PropertyActivity", "动画结束");
        }
    
        @Override
        public void onAnimationCancel(Animator animation) {
            Log.d("PropertyActivity", "动画取消");
        }
    
        @Override
        public void onAnimationRepeat(Animator animation) {
            Log.d("PropertyActivity", "动画重复");
        }
    });
    mValueAnimator.start();
    

这样就可以监听动画的开始、结束、被取消、重复等事件,但是有时候我们只需监听其中的某一个事件,比如动画的结束,此时可以添加AnimatorListenerAdapter,取代AnimatorListener。

    mValueAnimator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            Log.d("PropertyActivity", "动画结束");
        }
    });

从AnimatorListenerAdapter源码中可以清晰的看出,AnimatorListenerAdapter是一个抽象类,其实现了Animator.AnimatorListener和Animator.AnimatorPauseListener两个接口,并对接口中的方法空实现。通过添加AnimatorListenerAdapter来监听动画时,没有必要在实现接口的中的方法,只要选择你需要的那个回调并重写即可。

public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener,
        Animator.AnimatorPauseListener {

    public void onAnimationCancel(Animator animation) {
    }

    public void onAnimationEnd(Animator animation) {
    }

    public void onAnimationRepeat(Animator animation) {
    }

    public void onAnimationStart(Animator animation) {
    }

    public void onAnimationPause(Animator animation) {
    }

    public void onAnimationResume(Animator animation) {
    }
}

Animator.AnimatorPauseListener

Animator.AnimatorPauseListener用于监听动画暂停时的场景,其与pause()、resume()方法一起在API 19新增的API,也就是说添加此监听,SDK版本应在19以上才可以使用。

Animator.AnimatorPauseListener内声明的监听回调方法:

onAnimationPause(Animator animation):动画暂停时回调(调用pause()方法)
onAnimationResume(Animator animation):之前动画暂停,动画回复时回调(调用resume())

mValueAnimator.addPauseListener(new Animator.AnimatorPauseListener() {
    @Override
    public void onAnimationPause(Animator animation) {
        Log.d("PropertyActivity", "动画暂停");
    }

    @Override
    public void onAnimationResume(Animator animation) {
        Log.d("PropertyActivity", "动画暂停");
    }
});

参考资料

  1. Android 属性动画(Property Animation) 完全解析 (上)
  2. Android 属性动画(Property Animation) 完全解析 (下)
  3. Android属性动画
  4. 官方文档-Property Animation
  5. 深入理解 Android 动画 Interpolator 类的使用
  6. 浅析Android动画(三),自定义Interpolator与TypeEvaluator

你可能感兴趣的:(android自定义view,Android进阶,android,animation,属性动画)