美文网首页
Property animation

Property animation

作者: passssssss | 来源:发表于2017-03-10 14:31 被阅读0次

    相关类

    interface
    interface describe
    Animator.AnimatorListener 动画监听An animation listener receives notifications from an animation.有四个方法onAnimationStart(Animator animation) onAnimationEnd(Animator animation) onAnimationCancel(Animator animation) onAnimationRepeat(Animator animation)
    Animator.AnimatorPauseListener 动画暂停监听A pause listener receives notifications from an animation when the animation is paused or resumed.``onAnimationPause(Animator animation) `onAnimationResume(Animator animation)
    LayoutTransition.TransitionListener(X) This interface is used for listening to starting and ending events for transitions.
    TimeAnimator.TimeListener(X) 此接口实现可将自身设置为TimeAnimator实例的更新监听器并接受回调,在每一帧上获得自动画开始以来的时间和自上一帧以来的时间间隔。Implementors of this interface can set themselves as update listeners to a TimeAnimator instance to receive callbacks on every animation frame to receive the total time since the animator started and the delta time since the last frame.
    TimeInterpolator A time interpolator defines the rate of change of an animation. This allows animations to have non-linear motion, such as acceleration and deceleration.
    TypeEvaluator Interface for use with the [setEvaluator(TypeEvaluator)]function. Evaluators allow developers to create animations on arbitrary property types, by allowing them to supply custom evaluators for types that are not automatically understood and used by the animation system.
    ValueAnimator.AnimatorUpdateListener 动画每一帧都会对此接口进行回调Implementors of this interface can add themselves as update listeners to an ValueAnimator instance to receive callbacks on every animation frame, after the current frame's values have been calculated for that ValueAnimator.
    ValueAnimator This class provides a simple timing engine for running animations which calculate animated values and set them on target objects.
    class
    class describe
    Animator 动画超类This is the superclass for classes which provide basic support for animations which can be started, ended, and have AnimatorListeners added to them.
    AnimatorInflater xml加载器,用来将Animator XML文件实例化并注入Animator类。
    AnimatorListenerAdapter This adapter class provides empty implementations of the methods from [Animator.AnimatorListener]Any custom listener that cares only about a subset of the methods of this listener can simply subclass this adapter class instead of implementing the interface directly.不知道这个类的意义是什么
    AnimatorSet 此类将一组Animator对象按指定的顺序播放。
    AnimatorSet.Builder 为方便向AnimatorSet加入animation对象(连同不同animation对象之间的关系)工具类。
    ArgbEvaluator 此计算器可作为类型内插器,于代表ARGB颜色的整型值之间。
    FloatEvaluator 此计算器可作为类型内插器,于浮点型数值之间。
    IntEvaluator 此计算器可作为类型内插器,于整型数值之间。
    Keyframe(X) 该类包含了一个animation类的time/value值对。
    LayoutTransition(X) 该类在 ViewGroup类中使得背景可以是自动的动画。
    ObjectAnimator ValueAnimator的子类,提供了对目标对象的属性动画的支持。
    PropertyValuesHolder(X) 该类载有一个属性的信息,以及此属性在动画过程需要用到的值。
    RectEvaluator(X) This evaluator can be used to perform type interpolation between Rect values.
    TimeAnimator(X) 该类为已经与系统中所有其他动画对象同步的监听器提供一个简单的回调机制。
    ValueAnimator 该类为运行中的动画对象提供一个简单的时间引擎,以便计算动画的值并将结果设置于目标对象。
    1. Animator
    2. Evaluator
    3. listener
    4. interpolator
    QQ图片20170310100617.png

    Animator

    属性动画主要的类都在android.animation命名空间下,Animator是属性动画的基类,其是一个抽象类,该类定义了许多重要的方法,如下所示:

    1. setDuration(long duration) 通过setDuration方法可以设置动画总共的持续时间,以毫秒为单位。

    2. start() 通过start方法可以启动动画,动画启动后不一定会立即运行。如果之前通过调用setStartDelay方法设置了动画延迟时间,那么会在经过延迟时间之后再运行动画;如果没有设置过动画的延迟时间,那么动画在调用了start()方法之后会立即运行。在调用了start()方法之后,动画的isStarted()方法就会返回true;在动画真正运行起来之后,动画的isRunning()方法就会返回true,这时候动画才会调用TimeInterpolator才开始工作计算属性在某个时刻的值。调用动画的start()方法所在的线程必须绑定了一个Looper对象,如果没有绑定就会报错。当然,UI线程(即主线程)早就默认绑定了一个Looper对象,所以在主线程中我们就无需担心这个问题。如果我们想在一个View上使用属性动画,那么我们应该保证我们是在UI线程上调用的动画的start()方法。start()方法运行后会触发动画监听器AnimatorListener的onAnimationStart方法的执行。

    3. setStartDelay(long startDelay) 可以通过调用setStartDelay方法设置动画的延迟运行时间,比如调用setStartDelay(1000)意味着动画在执行了start()方法1秒之后才真正运行,这种情况下,在调用了start()方法之后,isStarted()方法返回true,表示动画已经启动了,但是在start()方法调用后1s内,isRunning()方法返回false,表示动画还未真正运行,比如在start()方法调用后第0.5秒,由于动画还在延迟阶段,所以isRunning()返回false;在start()方法执行1秒之后,isStarted()方法还是返回true,isRunning()方法也返回了true,表示动画已经真正开始运行了。通过调用getStartDelay()方法可以返回我们设置的动画延迟启动时间,默认值是0。

    4. setInterpolator(TimeInterpolator value) 我们可以通过调用setInterpolator方法改变动画所使用的时间插值器,由于视图动画也需要使用时间插值器,所以我们可以使用android.view.animation命名空间下的一系列插值器,将其与属性动画一起工作。通过动画的getInterpolator方法可以获取我们设置的时间插值器。

    5. setTarget(Object target) 可以通过调用动画的setTarget方法设置其要操作的对象,这样可以更新该对象的某个属性值。实际上,该方法对于ValueAnimator作用不大,因为ValueAnimator不是直接与某个对象打交道的。setTarget方法对于ObjectAnimator作用较大,因为ObjectAnimator需要绑定某个要操作的对象,下面会详细介绍。

    6. pause() Android中API Level 19在Animator中加入了pause()方法,该方法可以暂停动画的执行。调用pause()方法的线程必须与调用start()方法的线程是同一个线程。如果动画还没有执行start()或者动画已经结束了,那么调用pause()方法没有任何影响,直接被忽略。当执行了pause()方法后,动画的isPaused()方法会返回true。pause()方法运行后会触发动画监听器AnimatorPauseListener的onAnimationPause方法的执行。

    7. resume() 如果动画通过调用pause()方法暂停了,那么之后可以通过调用resume()方法让动画从上次暂停的地方继续运行。resume()方法也是从API Level 19引入的,并且调用resume()方法的线程必须与调用start()方法的线程是同一个线程。如果动画没有处于暂停状态(即isPaused()返回false),那么调用resume()方法会被忽略。resume()方法运行后会触发动画监听器AnimatorPauseListener的onAnimationResume方法的执行。

    8. end end()方法执行后,动画会结束运行,直接从当前状态跳转到最终的完成状态,并将属性值分配成动画的终止值,并触发动画监听器AnimatorListener的onAnimationEnd方法的执行。

    9. cancel() cancel()方法执行后,动画也会结束运行,但是与调用end方法不同的是,其不会将属性值分配给动画的终止值。比如一个动画在400ms内将对象的x属性从0渐变为40,当运行到第200ms时调用了cancel()方法,那么属性x的最终值是20,而不是40,这是与调用end()方法不同的,如果在第200ms调用了end()方法,那么属性x的最终值是40。调用cancel()方法后,会先触发AnimatorListener的onAnimationCancel方法的执行,然后触发onAnimationEnd方法的执行。

    10. clone() Animator实现了Java.lang.Cloneable接口。Animator的clone()方法会对动画进行拷贝,但是该方法默认实现的只是浅拷贝,子类可以重写该方法以实现深拷贝。

    11. addListener (Animator.AnimatorListener listener) 可以通过addListener方法向Animator添加动画监听器,该方法接收的是AnimatorListener接口类型的参数,其具有四个方法:onAnimationStart、onAnimationCancel、onAnimationEnd、onAnimationRepeat。我们上面已经介绍了前三个方法,onAnimationRepeat方法会在动画在重复播放的时候被回调。Android中的AnimatorListenerAdapter类是个抽象类,其实现了AnimatorListener接口,并为所有方法提供了一个空实现。

    12. addPauseListener (Animator.AnimatorPauseListener listener) 可以通过addPauseListener方法可以向Animator添加动画暂停相关的监听器,该方法接收的是AnimatorPauseListener接口类型的参数,具有两个方法:onAnimationPause和onAnimationResume,上面已经提到过,在此不再赘述。AnimatorListenerAdapter同样也实现了AnimatorPauseListener接口,并为所有方法提供了一个空实现。

    过程

    1. 需要计算出某一时刻属性值应该是多少
    2. 需要将计算出的属性值赋值给动画的属性

    用法

    objectAnimator(ValueAnimator的封装类)

    ObjectAnimator是ValueAnimator的封装类,他不像ValueAnimator只实现了计算某一时刻的属性值,需要我们手动给target赋值,ObjectAnimator会自动给target赋值,前提是需要我们告诉ObjectAnimator需要的赋值的对象(target)是谁,ObjectAnimator重载了ofFloat``ofInt``ofObject``ofArgb

    1. ofFloat
                 ObjectAnimator.ofFloat(view,"scaleX",0f,100f) 
                        .setDuration(1000)
                        .start();
    

    可以看到定义的animator操作的对象是view,操作的值是scaleX,变化的范围是0-100,动画开始后,就会不断的调用target的setScaleX方法来改变target的scaleX的值,所以target必须要有setScaleX方法,否则动画无效。如果ofFloat只指定了一个float参数,则会调用target的getScaleX来获得动画开始时的初始属性。

    1. ofInt
      ofFloat一样
    2. ofArgb
            if (Build.VERSION.SDK_INT>21){
                int startColor=0xffffffff;
                int endColor = 0x00000000;
                ObjectAnimator.ofArgb(view,"backgroundColor",startColor,endColor)
                        .setDuration(1000)
                        .start();
            }
    
    1. ofObject
      ofObject需要使用evaluator配合使用
        class CharEvaluator implements TypeEvaluator<Integer>{
            @Override
            public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
                // fraction(n. 分数;部分;小部分;稍微) , 是动画的进度
                int startInt = (Integer) startValue;
                int startA = (startInt >> 24) & 0xff;
                int startR = (startInt >> 16) & 0xff;
                int startG = (startInt >> 8) & 0xff;
                int startB = startInt & 0xff;
    
                int endInt = (Integer) endValue;
                int endA = (endInt >> 24) & 0xff;
                int endR = (endInt >> 16) & 0xff;
                int endG = (endInt >> 8) & 0xff;
                int endB = endInt & 0xff;
    
                return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
                        (int)((startR + (int)(fraction * (endR - startR))) << 16) |
                        (int)((startG + (int)(fraction * (endG - startG))) << 8) |
                        (int)((startB + (int)(fraction * (endB - startB))));
            }
        }
    
            int startColor=0xffffffff;
            int endColor = 0x00000000;
            ObjectAnimator.ofObject(view,"backgroundColor",new CharEvaluator(),startColor,endColor)
            .setDuration(2000)
            .start();
    

    ObjectAnimator是指使用object来当属性设置给view,需要自定义TypeEvaluator来提供动画过程中每一帧的object,对于ofInt等,每一帧的值已经被系统封装好了。
    Q:1. text属性为什么无效 2. TypeEvaluator提供的方法会调用几次,调用次数怎么得来的

    ps:PropertyValuesHolder这是一个用来设置值的类,个人感觉这就是个鸡肋,能省事就省事,用这个类干屌。

    QQ图片20170310152826.png

    ValueAnimator

    相对于ObjectAnimator,ValueAnimator少了一层封装,所以ValueAnimator需要自己将得到的此刻的值通过
    Animator.AnimatorUpdateListener设置给view,

            int startInt = 65;
            int endInt = 90;
            ValueAnimator valueAnimator = ValueAnimator.ofInt(startInt,endInt);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    ((TextView) view).setText(animation.getAnimatedValue()+"");
                }
            });
            valueAnimator.setDuration(3000);
            valueAnimator.start();
    

    ValueAnimator在动画开始之后,会每隔一段时间(默认是10ms)调用一次onAnimatorUpdate,在onAnimatorUpdate中可以完成对属性的设置。

    ofInt ofFloat ofObject ofArbg用法类似,其中int与Argb的区别是不大,但是Argb更适合颜色便于理解,个人觉得int和argb一样。

    ofObject用法与ObjectAnimator的ofOject用法一样,需要实现TypeEvaluator

    AnimatorSet

    动画的集合,可以让多个动画并行或者顺序执行,

    1. 创建动画
    2. 将动画添加到AnimatorSet中
    3. 执行

    想实现多种多样的动画并行或者顺序执行,需要通过第二部选择合适的添加方式,

     //anim1实现TextView的旋转动画
        Animator anim1 = ObjectAnimator.ofFloat(textView, "rotation", 0f, 360f);
        anim1.setDuration(2000);
        //anim2和anim3TextView的平移动画
        Animator anim2 = ObjectAnimator.ofFloat(textView, "translationX", 0f, 300f);
        anim2.setDuration(3000);
        Animator anim3 = ObjectAnimator.ofFloat(textView, "translationY", 0f, 400f);
        anim3.setDuration(3000);
        //anim4实现TextView的伸缩动画
        Animator anim4 = ObjectAnimator.ofFloat(textView, "scaleX", 1f, 0.5f);
        anim4.setDuration(2000);
    
    
        //第一种方式
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playSequentially(anim1, anim2, anim4);
        animatorSet.playTogether(anim2, anim3);
        animatorSet.start();
    
        //第二种方式
        /*AnimatorSet anim23 = new AnimatorSet();
        anim23.playTogether(anim2, anim3);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playSequentially(anim1, anim23, anim4);
        animatorSet.start();*/
    
        //第三种方式
        /*AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(anim1).before(anim2);
        animatorSet.play(anim2).with(anim3);
        animatorSet.play(anim4).after(anim2);
        animatorSet.start();*/
    

    动画anim1用于旋转TextView,anim2用于在X轴方向偏移TextView,anim3用于在Y轴方向偏移TextView,anim4用于缩放TextView。我们在以上代码中提供了三种方式通过AnimationSet把这四个动画组合到一起,第二种方式和第三种方式被注释起来了。

    其实有很多种办法实现上述效果,这里只介绍一下上述三种方式的思路。

    1. 在第一种方式中,调用了animatorSet.playSequentially(anim1, anim2, anim4),该方法将anim1、anim2以及anim4按顺序串联起来放到了animatorSet中,这样首先会让动画anim1执行,anim1执行完成后,会依次执行动画anim2,执行完anim2之后会执行动画anim3。通过调用animatorSet.playTogether(anim2, anim3),保证了anim2和anim3同时执行,即动画anim1完成之后会同时运行anim2和anim3。

    2. 在第二种方式中,我们首先创建了一个AnimatorSet变量anim23,然后通过anim23.playTogether(anim2, anim3)将anim2和anim3组合成一个小的动画集合。然后我们再把anim1、anim23以及anim4一起传入到animatorSet.playSequentially(anim1, anim23, anim4)中,这样anim1、anim23、anim4会依次执行,而anim23中的anim2和anim3会同时执行。该方式同时也演示了可以将一个AnimatorSet作为动画的一部分放入另一个AnimatorSet中。

    3. 在第三种方式中,我们使用了AnimatorSet的play方法,该方法返回AnimatorSet.Builder类型,animatorSet.play(anim1).before(anim2)确保了anim1执行完了之后执行anim2,animatorSet.play(anim2).with(anim3)确保了anim2和anim3同时执行,animatorSet.play(anim4).after(anim2)确保了anim2执行完了之后执行anim4。需要说明的是animatorSet.play(anim1).before(anim2)与animatorSet.play(anim2).after(anim1)是完全等价的,之所以在上面代码中有的写before,有的写after,只是为了让大家多了解一下API。

    应用

    1. 贝塞尔曲线移动,Object为Point,修改pointXY值即可。

    相关文章

      网友评论

          本文标题:Property animation

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