属性动画

作者: 黑色海鸥 | 来源:发表于2017-06-08 13:40 被阅读53次

    学习,参考加部分信息拷贝,来自以下链接:
    动画原理讲解系列:
    http://blog.csdn.net/u013478336/article/details/52137385
    牛逼的自定义插值器:
    http://www.cnblogs.com/wondertwo/p/5327586.html
    Evaluator
    http://wiki.jikexueyuan.com/project/android-animation/5.html
    http://wiki.jikexueyuan.com/project/android-animation/6.html 讲evaluator字母的变化
    牛逼的动画原理讲解,但是没有仔细看的:
    http://www.jianshu.com/p/ee7e3d79006d
    其他:
    http://www.jianshu.com/p/733532041f46
    http://blog.csdn.net/lmj623565791/article/details/38067475/

    概述

    1.1 简述
    属性动画引入自Android 3.0(API 11),其原理是给定对象的一个或多个属性,指定其开始与结束时的值,通过时间插值生成不同的属性值,并调用更新方法将属性值设置到对象内,引起对象重绘,从而形成动画效果。比如,通过不断的设置View的宽高来更新View的展示,形成缩放效果等。

    1.2 属性动画相关概念
    一个属性动画执行需要的基本要素包括:承载动画执行的对象属性、动画持续时间和属性的变化区间。

    • Duration: 指定动画的执行时间,默认300ms
    • Time interpolation: 一个输入为动画真实时间的函数,以此函数来计算动画属性;其实重点在于函数上,这个函数定义的是动画的变化速率,举个例子来看:假如有个函数y=x,x是动画的真实执行时间,y是映射后的速度,则这个动画是恒速执行的;假如映射函数是y=x*x,这个动画是就是不断加速运行的,因为y的变化速率在不断的增大。
    • Repeat count and behavior: 动画重复次数表示动画需要被执行的次数,动画重复时的行为有两种:从头开始或者反转执行;在动画执行结束时,如果没有执行完指定次数,则继续执行;
    • Animator sets: 将多个动画效果组成动画集合并设置彼此间的执行顺序,可设三种执行顺序:一起执行、顺序执行和在指定时间执行。
    • Frame refresh delay: 指定多长时间刷新一次动画的帧,默认值是10ms一次,但最终取决于当前系统的繁忙程度和系统多快能相应定时器,基本上我们可以不用考虑。
    • 监听动画: 开始 / 结束 / 重复时刻
    anim.addListener(new AnimatorListenerAdapter() {  
    // 向addListener()方法中传入适配器对象AnimatorListenerAdapter()
    // 由于AnimatorListenerAdapter中已经实现好每个接口
    // 所以这里不实现全部方法也不会报错
        @Override  
        public void onAnimationStart(Animator animation) {  
        // 如想只想监听动画开始时刻,就只需要单独重写该方法就可以
        }  
    });
    

    1.3 属性动画与补间动画的区别
    应用对象不同,本质不同,适用范围有包含关系。

    • 补间动画的应用对象只能是View,不能用于非View对象,属性动画支持任意对象;
    • 补间动画的本质是对View做Transformation,并不能影响View的布局位置,只能影响View的可视位置。如果View从屏幕左边移动到右边,则其展示在右边了,但是这时候View相应点击事件还是在左边的位置,因为View并没有真的移动到右边,只是被绘制到右边了;
    • 及时动画对象是View,补间动画能做的也比较有限,只能做平移/旋转/缩放/透明度四种变化效果,假如我们要不断改变View背景色,就搞不定了,属性动画表示毫无压力;
    • 属性动画比补间动画更灵活,可以同时支持多个属性的动画,每个属性都可以独立定义插值器,各动画之间还可以做动画同步控制。
    属性动画有关类的继承关系

    1.4 Interpolator vs evaluator

    • Interpolator: 插值器, 用来定义animator变化的速率 (加速、减速...)
    系统带的一些插值器.png

    AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速
    AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
    AnticipateInterpolator 开始的时候向后然后向前甩
    AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
    BounceInterpolator 动画结束的时候弹起
    CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
    DecelerateInterpolator 在动画开始的时候快然后慢
    LinearInterpolator 以常量速率改变
    OvershootInterpolator 向前甩一定值后再回到原来位置

    • evaluator: 返回动画在当前时间点所需要的值
      我们可以把动画的过程想象成是一部电影的播放,电影的播放中有进度条,Interpolator就是用来控制电影播放频率,也就是快进快退要多少倍速。然后Evaluator根据Interpolator提供的值(fraction)计算当前播放电影中的哪一个画面,也就是进度条要处于什么位置。

    1.5 动画的过程中所涉及的计算

    • ValueAnimator对象会根据动画的总时间和已经流逝的时间计算出一个0到1之间的elapsed fraction值。这个elapsed fraction值就代表了时间完成的程度

    • 计算出elapsed fraction之后,ValueAnimator对象会调用TimeInterpolator
      来计算一个interpolated fraction,即,根据所设置的时间插值方法将elapsed fraction映射到interpolated fraction。 interpolated fraction 可能大于、小于、等于elapsed fraction,就看使用的什么插值器了。

    • interpolated fraction计算出来后,ValueAnimator 会调用TypeEvaluator,来进行你要动画的属性值的计算。
      这时候用的输入参数就是interpolated fraction的值,以及属性值的起始值和终止值。

    动画计算流程图.png

    ValueAnimator

    • 构造
      ValueAnimator.ofArgb
      ValueAnimator.ofInt
      ValueAnimator.ofFloat
      ValueAnimator.ofObject
      ValueAnimator.ofPropertyValuesHolder
    ValueAnimator animator = ValueAnimator.ofInt(0, 400);
     animator.setDuration(1000);
      animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int curValue = (int) animation.getAnimatedValue();
                    tv.layout(curValue, curValue, curValue + tv.getWidth(), curValue + tv.getHeight());
                }
            });
     animator.start();
    

    PropertyValuesHolder

    1. 保存了动画过程中所需要操作的属性和对应的值。
    2. 我们通过 ofInt(Object target, String propertyName, int… values)构造的动画,ofInt()的内部实现其实就是将传进来的参数封装成 PropertyValuesHolder 实例来保存动画状态。
    3. 在封装成 PropertyValuesHolder 实例以后,后期的各种操作也是以 PropertyValuesHolder 为主的。

    自定义ValueAnimator

    ObjectAnimator

    ValueAnimator 有个缺点,就是只能对数值对动画计算。想对哪个控件操作,需要监听动画过程,在监听中对控件操作。
    为了能让动画直接与对应控件相关联,以使我们从监听动画过程中解放出来在 ValueAnimator 的基础上,又派生了一个类 ObjectAnimator;
    先看看利用 ObjectAnimator 重写的 ofFloat 方法如何实现一个动画:(改变透明度)

    ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"alpha",1,0,1);  
    animator.setDuration(2000);  
    animator.start(); 
    
    1. 要使用 ObjectAnimator 来构造对画,要操作的控件中,必须存在对应的属性的 set 方法
    2. setter 方法的命名必须以骆驼拼写法命名,即 set 后每个单词首字母大写,其余字母小写,即类似于 setPropertyName 所对应的属性为 propertyName ;
      set 函数调用频率是多少:动画在进行时,每隔十几毫秒会刷新一次,所以我们的 set 函数也会每隔十几毫秒会被调用一次。
      系统会根据属性通过反射找到对应属性的设置方法,刷新其值
    3. 何时需要实现对应属性的 get 函数。构造方法中最后一个参数都是可变长参数,从哪个值变到哪个值的,如果值传入了一个值,那默认值最终值,起始值就从get属性获取。

    **自定义ObjectAnimator **

    AnimatorSet

    • AnimatorSet 针对 ValueAnimator 和 ObjectAnimator 都是适用的;
    • playSequentially 表示所有动画依次播放,playTogether 表示所有动画一起开始。
    • setTarget属性,在 AnimatorSet 中设置以后,会覆盖单个 ObjectAnimator 中的设置;即如果 AnimatorSet 中没有设置,那么就以 ObjectAnimator 中的设置为准。

    自定义Interpolator

    public class AccelerateDecelerateInterpolator extends BaseInterpolator
            implements NativeInterpolatorFactory {
        public AccelerateDecelerateInterpolator() {
        }
    
        @SuppressWarnings({"UnusedDeclaration"})
        public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
        }
    
        public float getInterpolation(float input) {
            return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
        }
    
        /** @hide */
        @Override
        public long createNativeInterpolator() {
            return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();
        }
    }
    

    换成数学表达式

    {0.5*cos[(input + 1)π] + 0.5}
    
    余弦函数.png

    在0-1之间,增长速度是先变快,后匀速,最后慢慢变慢

    相关文章

      网友评论

        本文标题:属性动画

        本文链接:https://www.haomeiwen.com/subject/ycmafxtx.html