• 属性动画


    Android 3.0以后引入了属性动画,属性动画可以轻而易举的实现许多View动画做不到的事,

    属性动画实现原理就是修改控件的属性值实现的动画。

    具体先看下类关系:


    Android属性动画(注意最低兼容版本,不过可以使用开源项目来替代低版本问题)提供了以下属性:

    • Duration:动画的持续时间;
    • TimeInterpolation:定义动画变化速率的接口,所有插值器都必须实现此接口,如线性、非线性插值器;
    • TypeEvaluator:用于定义属性值计算方式的接口,有int、float、color类型,根据属性的起始、结束值和插值一起计算出当前时间的属性值;
    • Animation sets:动画集合,即可以同时对一个对象应用多个动画,这些动画可以同时播放也可以对不同动画设置不同的延迟;
    • Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响;
    • Repeat Country and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以让此动画一直重复,或播放完时向反向播放;

     

    XML方式属性动画代码示例

    在xml中可直接用的属性动画节点有ValueAnimator、ObjectAnimator、AnimatorSet。如下是官方的一个例子和解释

    
    
    <set
      android:ordering=["together" | "sequentially"]>
    
        <objectAnimator
            android:propertyName="string"
            android:duration="int"
            android:valueFrom="float | int | color"
            android:valueTo="float | int | color"
            android:startOffset="int"
            android:repeatCount="int"
            android:repeatMode=["repeat" | "reverse"]
            android:valueType=["intType" | "floatType"]/>
    
        <animator
            android:duration="int"
            android:valueFrom="float | int | color"
            android:valueTo="float | int | color"
            android:startOffset="int"
            android:repeatCount="int"
            android:repeatMode=["repeat" | "reverse"]
            android:valueType=["intType" | "floatType"]/>
    
        <set>
            ...
        </set>
    </set>

     


    <set>属性

    <objectAnimator>属性

    ValueAnimator同上<objectAnimator>属性

    XML属性动画使用方法

    AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,R.animtor.property_animator);
    set.setTarget(myObject);set.start();
    

     Java方式属性动画

    1、ObjectAnimator:继承自ValueAnimator,允许你指定要进行动画的对象以及该对象的一个属性。该类会根据计算得到的新值自动更新属性。大多数的情况使用ObjectAnimator就足够了,因为它使得目标对象动画值的处理过程变得足够简单,不用像ValueAnimator那样自己写动画更新的逻辑,但是ObjectAnimator有一定的限制,比如它需要目标对象的属性提供指定的处理方法(譬如提供getXXX,setXXX方法),这时候你就需要根据自己的需求在ObjectAnimator和ValueAnimator中看哪种实现更方便了。

    ObjectAnimator类提供了ofInt、ofFloat、ofObject这个三个常用的方法,这些方法都是设置动画作用的元素、属性、开始、结束等任意属性值。当属性值(上面方法的参数)只设置一个时就把通过getXXX反射获取的值作为起点,设置的值作为终点;如果设置两个(参数),那么一个是开始、另一个是结束。

    特别注意:ObjectAnimator的动画原理是不停的调用setXXX方法更新属性值,所有使用ObjectAnimator更新属性时的前提是Object必须声明有getXXX和setXXX方法。我们通常使用ObjectAnimator设置View已知的属性来生成动画,而一般View已知属性变化时都会主动触发重绘图操作,所以动画会自动实现;但是也有特殊情况,譬如作用Object不是View,或者作用的属性没有触发重绘,或者我们在重绘时需要做自己的操作,那都可以通过如下方法手动设置:

       ObjectAnimator mObjectAnimator= ObjectAnimator.ofInt(view, "customerDefineAnyThingName", 0,  1) .setDuration(2000);
           mObjectAnimator.addUpdateListener(new AnimatorUpdateListener()
            {
                @Override
                public void onAnimationUpdate(ValueAnimator animation)
                {
                    //int value = animation.getAnimatedValue();  可以获取当前属性值
                    //view.postInvalidate();  可以主动刷新
                    //view.setXXX(value);
                    //view.setXXX(value);
                    //......可以批量修改属性
                }
            });
    

     在项目中的Y轴3D旋转动画实现实例:

    ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f).setDuration(1000).start();
    

    2、PropertyValuesHolder:多属性动画同时工作管理类。有时候我们需要同时修改多个属性,那就可以用到此类,具体如下:

    PropertyValuesHolder a1 = PropertyValuesHolder.ofFloat("alpha", 0f, 1f); 
    PropertyValuesHolder a2 = PropertyValuesHolder.ofFloat("translationY", 0, viewWidth); 
    ......
    ObjectAnimator.ofPropertyValuesHolder(view, a1, a2, ......).setDuration(1000).start();
    

    如上代码就可以实现同时修改多个属性的动画啦。

    3、ValueAnimator:属性动画中的时间驱动,管理着动画时间的开始、结束属性值,相应时间属性值计算方法等。包含所有计算动画值的核心函数以及每一个动画时间节点上的信息、一个动画是否重复、是否监听更新事件等,并且还可以设置自定义的计算类型。

    特别注意:ValueAnimator只是动画计算管理驱动,设置了作用目标,但没有设置属性,需要通过updateListener里设置属性才会生效。

    ValueAnimator animator = ValueAnimator.ofFloat(0, mContentHeight);  //定义动画
    animator.setTarget(view);   //设置作用目标
    animator.setDuration(5000).start();
    animator.addUpdateListener(new AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation){
            float value = (float) animation.getAnimatedValue();
            view.setXXX(value);  //必须通过这里设置属性值才有效
            view.mXXX = value;  //不需要setXXX属性方法
        }
    });
    

    看上去可以发现和ObjectAnimator没啥区别,实际上正是由于ValueAnimator不直接操作属性值,所以要操作对象的属性可以不需要setXXX与getXXX方法,你完全可以通过当前动画的计算去修改任何属性。

    4、AnimationSet:动画集合,提供把多个动画组合成一个组合的机制,并可设置动画的时序关系,如同时播放、顺序播放或延迟播放。具体使用方法比较简单,如下:

    ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0f); 
    ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "translationY", 0f, viewWidth); 
    ......
    AnimatorSet animSet = new AnimatorSet(); 
    animSet.setDuration(5000); 
    animSet.setInterpolator(new LinearInterpolator());  
    //animSet.playTogether(a1, a2, ...); //两个动画同时执行 
    animSet.play(a1).after(a2); //先后执行
    ......//其他组合方式
    animSet.start();
    

    5、Evaluators相关类解释: Evaluators就是属性动画系统如何去计算一个属性值。它们通过Animator提供的

    动画的起始和结束值去计算一个动画的属性值。

    •  IntEvaluator:   整数属性值。

    •  FloatEvaluator: 浮点数属性值。

    •  ArgbEvaluator:  十六进制color属性值。

    •  TypeEvaluator:  用户自定义属性值接口,譬如对象属性值类型不是int、float、color类型,

                           你必须实现这个接口去定义自己的数据类型

    如需要实现一个自定义属性类型和计算规则的属性动画,如下类型float[]:

    ValueAnimator valueAnimator = new ValueAnimator();
    valueAnimator.setDuration(5000);
    valueAnimator.setObjectValues(new float[2]); //设置属性值类型
    valueAnimator.setInterpolator(new LinearInterpolator());
    valueAnimator.setEvaluator(new TypeEvaluator<float[]>()
    {
        @Override
        public float[] evaluate(float fraction, float[] startValue,float[] endValue)
        {
            //实现自定义规则计算的float[]类型的属性值
            float[] temp = new float[2];
            temp[0] = fraction * 2;
            temp[1] = (float)Math.random() * 10 * fraction;
            return temp;
        }
    });
    valueAnimator.start();
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
    {
        @Override
        public void onAnimationUpdate(ValueAnimator animation)
        {
            float[] xyPos = (float[]) animation.getAnimatedValue();
            view.setHeight(xyPos[0]);   //通过属性值设置View属性动画
            view.setWidth(xyPos[1]);    //通过属性值设置View属性动画
        }
    });
    
     
    

    6、Interpolators相关类解释

    •  AccelerateDecelerateInterolator:先加速后减速。

    •  AccelerateInterpolator:加速。

    •  DecelerateInterpolator:减速。

    •  AnticipateInterpolator:先向相反方向改变一段再加速播放。

    •  AnticipateOvershootInterpolator:先向相反方向改变,再加速播放,会超出目标值然后缓慢移动至目标值,类似于弹簧回弹。

    •  BounceInterpolator:快到目标值时值会跳跃。

    •  CycleIinterpolator:动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)。

    •  LinearInterpolator:线性均匀改变。

    •  OvershottInterpolator:最后超出目标值然后缓慢改变到目标值。

    •  TimeInterpolator:一个允许自定义Interpolator的接口,以上都实现了该接口。

    如下就是加速插值器的实现代码,我们自定义时也可以类似实现:

      

     //开始很慢然后不断加速的插值器。
        public class AccelerateInterpolator implements Interpolator {
        private final float mFactor;
        private final double mDoubleFactor;
        public AccelerateInterpolator() {
            mFactor = 1.0f;
            mDoubleFactor = 2.0;
        }
        ......
        //input  0到1.0。表示动画当前点的值,0表示开头,1表示结尾。
        //return  插值。值可以大于1超出目标值,也可以小于0突破低值。
        @Override
        public float getInterpolation(float input) {
            //实现核心代码块
            if (mFactor == 1.0f) {
                return input * input;
            } else {
                return (float)Math.pow(input, mDoubleFactor);
            }
        }
    }
    

    综上可以发现,我们可以使用现有系统提供标准的东东实现属性动画,也可以通过自定义继承相关接口实现自己的动画,只要实现上面提到的那些主要方法即可。


    Java属性动画拓展之ViewPropertyAnimator动画

    在Android API 12时,View中添加了animate方法,具体如下:

    p

    ublic class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {
         ......
         /**
         * This method returns a ViewPropertyAnimator object, which can be used to animate
         * specific properties on this View.
         *
         * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
         */
        public ViewPropertyAnimator animate() {
            if (mAnimator == null) {
                mAnimator = new ViewPropertyAnimator(this);
            }
            return mAnimator;
        }
        ......
    }
    

    可以看见通过View的animate()方法可以得到一个ViewPropertyAnimator的属性动画(有人说他没有继承Animator类,是的,他是成员关系,不是之前那种继承关系)。

    ViewPropertyAnimator提供了一种非常方便的方法为View的部分属性设置动画(切记,是部分属性),它可以直接使用一个Animator对象设置多个属性的动画;在多属性设置动画时,它比 上面的ObjectAnimator更加牛逼、高效,因为他会管理多个属性的invalidate方法统一调运触发,而不像上面分别调用,所以还会有一些性能优化。

    如下就是一个例子:

    myView.animate().x(0f).y(100f).start();
    

    Java属性动画拓展之LayoutAnimator容器布局动画

    Property动画系统还提供了对ViewGroup中View添加时的动画功能,我们可以用LayoutTransition对ViewGroup中的View进行动画设置显示。LayoutTransition的动画效果都是设置给ViewGroup,然后当被设置动画的ViewGroup中添加删除View时体现出来。该类用于当前布局容器中有View添加、删除、隐藏、显示等时候定义布局容器自身的动画和View的动画,也就是说当在一个LinerLayout中隐藏一个View的时候,我们可以自定义 整个由于LinerLayout隐藏View而改变的动画,同时还可以自定义被隐藏的View自己消失时候的动画等。

    我们可以发现LayoutTransition类中主要有五种容器转换动画类型,具体如下:

    •  LayoutTransition.APPEARING:       当View出现或者添加的时候View出现的动画。

    •  LayoutTransition.CHANGE_APPEARING:当添加View导致布局容器改变的时候整个布局容器的动画。

    •  LayoutTransition.DISAPPEARING:    当View消失或者隐藏的时候View消失的动画。

    •  LayoutTransition.CHANGE_DISAPPEARING:当删除或者隐藏View导致布局容器改变的时候整个布局容器的动画。

    •  LayoutTransition.CHANGE:当不是由于View出现或消失造成对其他View位置造成改变的时候整个布局容器的动画

    XML方式使用系统提供的默认LayoutTransition动画:

    我们可以通过如下方式使用系统提供的默认ViewGroup的LayoutTransition动画:

    android:animateLayoutChanges=”true”
    

    在ViewGroup添加如上xml属性默认是没有任何动画效果的,因为前面说了,该动画针对于ViewGroup内部东东发生改变时才有效,

    所以当我们设置如上属性然后调运ViewGroup的addView、removeView方法时就能看见系统默认的动画效果了。

    还有一种就是通过如下方式设置:

    android:layoutAnimation=”@anim/customer_anim”
    

    通过这种方式就能实现很多吊炸天的动画。


    Java方式使用系统提供的默认LayoutTransition动画

    在使用LayoutTransition时,你可以自定义这几种事件类型的动画,也可以使用默认的动画,总之最终都是通过setLayoutTransition(LayoutTransition lt)方法把这些动画以一个LayoutTransition对象设置给一个ViewGroup。

    譬如实现如上Xml方式的默认系统LayoutTransition动画如下:

    mTransitioner = new LayoutTransition();
    mViewGroup.setLayoutTransition(mTransitioner);
    

    稍微再高端一点吧,我们来自定义这几类事件的动画,分别实现他们,那么你可以像下面这么处理:

    mTransitioner = new LayoutTransition();
    ......
    ObjectAnimator anim = ObjectAnimator.ofFloat(this, "scaleX", 0, 1);
    ......//设置更多动画
    mTransition.setAnimator(LayoutTransition.APPEARING, anim);
    ......//设置更多类型的动画             
    mViewGroup.setLayoutTransition(mTransitioner);
    

    通过LayoutTransition就能实现类似小米手机计算器切换普通型和科学型的炫酷动画了。

  • 相关阅读:
    大二(上期)学期末个人学习总结
    《梦断代码》阅读笔记01
    软件工程概论课程评价
    03《构建之法》阅读笔记第三篇(终结篇)
    02《构建之法》阅读笔记第二篇
    个人简评——2345王牌拼音输入法
    《人件集》阅读笔记第一篇
    个人学习进度条
    AcWing ST算法(区间求最值)打卡
    AcWing 101. 最高的牛 (差分) 打卡
  • 原文地址:https://www.cnblogs.com/loaderman/p/6437221.html
Copyright © 2020-2023  润新知