总结系列-Android 属性动画

Posted ZhangQiang-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了总结系列-Android 属性动画相关的知识,希望对你有一定的参考价值。

android一开始提供了视图动画,即补间动画跟逐帧动画。但视图动画存在三个问题 (如下), 为了弥补视图动画的缺陷,Android在3.0(API 11)开始提供了一种全新的动画模式:属性动画(Property Animation)。 对于属性动画的使用,主要是: 1. 两个使用方法类:ValueAnimator 类 & ObjectAnimator 类 2. 两个辅助使用类:插值器( Interpolator )(插值器范例) & 估值器( TypeEvaluator )

1 ValueAnimator类

  • 实现动画的原理: 通过不断控制 值 的变化,再不断 手动 赋给对象的属性,从而实现动画效果。如图下:
从上面原理可以看出:ValueAnimator类中有3个重要方法(3个方法类似,以一个方法举例): ValueAnimator.ofInt(int values) ValueAnimator.ofFloat(float values)

ValueAnimator.ofObject(int values)

方式一:
// 步骤1:设置动画属性的初始值 & 结束值
ValueAnimator anim = ValueAnimator.ofInt(0, 3);
// ofInt()作用有两个
// 1. 创建动画实例
// 2. 将传入的多个Int参数进行平滑过渡:此处传入0和1,表示将值从0平滑过渡到1 ; 如果传入了3个Int参数 a,b,c ,则是先从a平滑过渡到b,再从b平滑过渡到C,以此类推
// ValueAnimator.ofInt()内置了整型估值器,直接采用默认的.不需要设置,即默认设置了如何从初始值 过渡到 结束值

    anim.setDuration(500);// 设置动画运行的时长
    anim.setStartDelay(500);// 设置动画延迟播放时间
    anim.setRepeatCount(0);// 设置动画重复播放次数 = 重放次数+1  // 动画播放次数 = infinite时,动画无限重复
    anim.setRepeatMode(ValueAnimator.RESTART); // RESTART(默认):正序重放  ;  REVERSE:倒序回放
    // 设置重复播放动画模式
    // ValueAnimator.
    // ValueAnimator.

// 即:值每次改变、变化一次,该方法就会被调用一次
    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() 
    @Override
    public void onAnimationUpdate(ValueAnimator animation) 
        // 获得改变后的值
        int currentValue = (Integer) animation.getAnimatedValue();
        // 步骤4:将改变后的值赋给对象的属性值,下面会详细说明
        View.setproperty(currentValue);
    
);
// 启动动画
    anim.start();

方式二:
步骤1:在路径 res/animator的文件夹里创建相应的动画 .xml文件
步骤2:设置动画参数 set_animation.xml
// ValueAnimator采用<animator>  标签
<animator xmlns:android="http://schemas.android.com/apk/res/android"  
    android:valueFrom="0"   // 初始值
    android:valueTo="100"  // 结束值
    android:valueType="intType" // 变化值类型 :floatType & intType

    android:duration="3000" // 动画持续时间(ms),必须设置,动画才有效果
    android:startOffset ="1000" // 动画延迟开始时间(ms)
    android:fillBefore = “true” // 动画播放完后,视图是否会停留在动画开始的状态,默认为true
    android:fillAfter = “false” // 动画播放完后,视图是否会停留在动画结束的状态,优先于fillBefore值,默认为false
    android:fillEnabled= “true” // 是否应用fillBefore值,对fillAfter值无影响,默认为true
    android:repeatMode= “restart” // 选择重复播放动画模式,restart代表正序重放,reverse代表倒序回放,默认为restart|
    android:repeatCount = “0” // 重放次数(所以动画的播放次数=重放次数+1),为infinite时无限重复
    android:interpolator = @[package:]anim/interpolator_resource // 插值器,即影响动画的播放速度,下面会详细讲
/>  

步骤3:在Java代码中启动动画
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.set_animation);   // 载入XML动画
animator.setTarget(view);  // 设置动画对象
animator.start();   // 启动动画


特别注意
ValueAnimator.ofFloat和ValueAnimator.ofObject类似 ,其实ValueAnimator.ofObject()的本质还是操作 值,只是是采用将 多个值 封装到一个对象里的方式 同时对多个值一起操作而已 .
ValueAnimator.ofObject需要一个插值器

ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
.....
// 实现TypeEvaluator接口
public class PointEvaluator implements TypeEvaluator 
    // 复写evaluate()
    // 在evaluate()里写入对象动画过渡的逻辑
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) 

        // 将动画初始值startValue 和 动画结束值endValue 强制类型转换成Point对象
        Point startPoint = (Point) startValue;
        Point endPoint = (Point) endValue;

        // 根据fraction来计算当前动画的x和y的值
        float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
        float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
        
        // 将计算后的坐标封装到一个新的Point对象中并返回
        Point point = new Point(x, y);
        return point;
    

2 ObjectAnimator类

动画的原理 直接对对象的属性值进行改变操作,从而实现动画效果

  1. 如直接改变  View的  alpha 属性 从而实现透明度的动画效果
  2. 继承自 ValueAnimator类,即底层的动画实现机制是基于 ValueAnimator
从上面的工作原理可以看出:ObjectAnimator与 ValueAnimator类的区别:
  • ValueAnimator 类是先改变值,然后 手动赋值 给对象的属性从而实现动画;是 间接 对对象属性进行操作;( ValueAnimator  类本质上是一种 改变 值 的操作机制)
  • ObjectAnimator 类是先改变值,然后 自动赋值 给对象的属性从而实现动画;是 直接 对对象属性进行操作;( ObjectAnimator 更加智能、自动化程度更高)
注: * ObjectAnimator 类针对的是任意对象 & 任意属性值,并不是单单针对于View对象      * 如果需要采用ObjectAnimator 类实现动画效果,那么需要操作的对象就 必须有该属性的set()、get()      * 由于View的setWidth()并不是设置View的宽度,而是设置View的最大宽度和最小宽度的,所以通过 setWidth()无法改变控件的宽度,即对View视图的width做属性动画没有效果  
使用方式一:
// 步骤1:创建ObjectAnimator对象
// 2. 参数设置: // Object object:需要操作的对象 // String property:需要操作的对象的属性 // float ....values:动画初始值 & 结束值(不固定长度)
// 至于如何从初始值过渡到结束值,同样是由估值器决定,此处ObjectAnimator.ofFloat()是有系统内置的浮点型估值器FloatEvaluator,同ValueAnimator讲解
ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String property, float ....values);
// 步骤3:启动动画
animator.start();

使用实例-而 自动赋给对象的属性的本质是调用该对象属性的set() 、get()方法进行赋值。
平移: ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, "translationX", curTranslationX, 300,curTranslationX);
旋转: ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, "rotation", 0f, 360f);
缩放: ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, "scaleX", 1f, 3f, 1f);
透明度: ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, "alpha", 1f, 0f, 1f);
使用方式二:
    // 步骤1:在路径 res/animator 的文件夹里创建动画效果.xml文件 // set_animation.xml
    // ObjectAnimator 采用<animator>  标签
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="1"   // 初始值
    android:valueTo="0"  // 结束值
    android:valueType="floatType"  // 变化值类型 :floatType & intType
    android:propertyName="alpha" // 对象变化的属性名称
            />
    .......
    Animator animator = AnimatorInflater.loadAnimator(context, R.animator.view_animation);// 1. 载入XML动画
    animator.setTarget(view);// 2. 设置动画对象
    animator.start(); // 3. 启动动画

多个动画合并播放: AnimatorSet
playTogether:同时播放         playSequentially: 顺序播放
fun startAnimation() 
    val anim1Set = AnimatorSet()
    anim1Set.playTogether(getAnim1_X(), getAnim1_Y())

    val anim1Set2 = AnimatorSet()
    anim1Set2.playTogether(getAnim2_X(), getAnim2_Y())

    val anim6Set = AnimatorSet()
    anim6Set.playTogether(getAnim6_X(), getAnim6_Y())

    mAnimatorSet.playSequentially(anim1Set, anim1Set2, getAnim3(), getAnim4(), getAnim5(), anim6Set)
    mAnimatorSet.start()

3.插值器: 

定义:Android实现动画效果中的一个辅助接口 作用:设置 属性值 从初始值过渡到结束值 的变化规律 , 如匀速、加速 & 减速 等等 , 即确定了 动画效果变化的模式,如匀速变化、加速变化 等等 Android内置了 9 种内置的插值器实现(默认 AccelerateDecelerateInterpolator先加速后减速 ): 自定义插值器: 对input值 根据动画的进度(0%-100%)通过逻辑计算 计算出当前属性值改变的百分比

4.估值器: 

应用场景:  协助插值器 实现非线性运动的动画效果 具体使用:
ObjectAnimator anim = ObjectAnimator.ofObject(myView2, "height", new Evaluator(),1,3);
// 在第4个参数中传入对应估值器类的对象
// 系统内置的估值器有3个:// IntEvaluator:以整型的形式从初始值 - 结束值 进行过渡
// FloatEvaluator:以浮点型的形式从初始值 - 结束值 进行过渡
// ArgbEvaluator:以Argb类型的形式从初始值 - 结束值 进行过渡
自定义估值器 根据 插值器计算出当前属性值改变的百分比 & 初始值 & 结束值 来计算 当前属性具体的数值 如:动画进行了50%(初始值=100,结束值=200 ),那么匀速插值器计算出了当前属性值改变的百分比是50%,那么估值器则负责计算当前属性值 = 100 + (200-100)x50% = 150. 示例:
// 实现TypeEvaluator接口public class PointEvaluator implements TypeEvaluator 
    // 复写evaluate()
    // 在evaluate()里写入对象动画过渡的逻辑
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) 

        // 将动画初始值startValue 和 动画结束值endValue 强制类型转换成Point对象
        Point startPoint = (Point) startValue;
        Point endPoint = (Point) endValue;

        // 根据fraction来计算当前动画的x和y的值
        float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
        float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
        
        // 将计算后的坐标封装到一个新的Point对象中并返回
        Point point = new Point(x, y);
        return point;
    
插值器与估值器的区别

以上是关于总结系列-Android 属性动画的主要内容,如果未能解决你的问题,请参考以下文章

总结系列-Android 属性动画

总结系列-Android 属性动画

)

Android动画总结

Android动画 三种动画

Android 动画系列之补间(Tween)动画详解