美文网首页
ValueAnimator详解

ValueAnimator详解

作者: 钉某人 | 来源:发表于2017-10-28 13:20 被阅读0次

    Android动画共分为两种:View Animation(视图动画)和Property Animator(属性动画)

    • View Animation 包括 Tween Animation(补间动画)和 Frame Animation(逐帧动画)
    • Property Animator 包括 ValueAnimator 和 ObjectAnimation

    View Animation 和 Property Animator的区别:

    区别 View Animation Property Animator
    引入时间 API Level 1 API Level 11
    所在包名 android.view.animation android.animation
    命名 XXXXAnimation XXXXAnimator
    作用对象 控件 控件属性




    这里以TranslateAnimation位移动画为例,补间动画改变的只是控件的显示位置,没有改变控件的实际位置。这个过程是由Parent View来实现的,在View被绘制时,Parent View改变View的 绘制参数,这个View就会发生对应的位移动画,但是View的实际参数并没有改变。对应的View在移动过程中和移动后是没有点击效果的,然而在View原来的点击区域,可能此时已经不可见,但是仍然可以有点击效果。属性动画就恰恰相反,属性动画是通过改变控件的内部属性值来实现动画效果。


    简单使用:

    这里写图片描述
     valueAnimator = ValueAnimator.ofInt(10,800);
              valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                  @Override
                  public void onAnimationUpdate(ValueAnimator animation) {
                      int value = (int) animation.getAnimatedValue();
                      tv.setText("值:"+value);
                      img.layout((int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,16,getResources().getDisplayMetrics())+value), (int) img.getY(),
                              (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,16,getResources().getDisplayMetrics())+value+img.getWidth()),(int) img.getY()+img.getHeight());//坐标以父控件为基准
                  }
              });
              valueAnimator.setDuration(1000);
              valueAnimator.start();
    
    

    基本的的api使用,请查看api文档,这里我们将一些别的。


    取消监听的方法

     /*
      * 移除 AnimatorUpdateListener
      */
      void removeUpdateListener(AnimatorUpdateListener listener);
      void removeAllUpdateListeners();
       /*
        * 移除 AnimatorListener
        */
      void removeListener(AnimatorListener listener);
      void removeAllListeners();
      /*
       * 延时多久时间开始,单位是毫秒
       */
      public void setStartDelay(long startDelay)
      /*
       * 完全克隆一个 ValueAnimator 实例,包括它所有的设置以及所有对监听器代码的处理
       * 就像克隆羊一样,克隆羊拥有母体所有的特征,但是完成克隆之后,就是新的生命体,跟母体也就没有任何关系了
       */
      public ValueAnimator clone()
    

    Evaluator计算器

    这里写图片描述
    Evaluator其实就是一个转换器,将小数进度转换成对应的数值。Evaluator都是专用的,比如ofInt(int...),那么对应的Evaluator必然要返回int类型的值,否则就会报强转的错误。valueAnimator.setEvaluator()来设置转换器.


    IntEvaluator源码:
    public class IntEvaluator implements TypeEvaluator<Integer> {
        public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
            int startInt = startValue;
            return (int)(startInt + fraction * (endValue - startInt));
        }
    }
    

    其中 fraction 就是插值器中的返回值,表示当前动画的数值进度,百分制的小数表示。 startValue 和 endValue 分别对应 ofInt(int start,int end)中的 start 和 end 的数值;

    自定义Evaluator

    public class MyEvaluator implements TypeEvaluator<Integer> {
        @Override
        public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
            int startInt = startValue;
            return (int)(200+startInt + fraction * (endValue - startInt));
        }
    }
    

    所以我们可以通过自定义插值器改变数值进度来改变数值位置,也可以通过自定义Evaluator改变进度所对应数值来改变数值位置。

    ArgbEvaluator色值过渡计算器

    例子:

     valueAnimator = ValueAnimator.ofInt(0xfff10f0f,0xfff10fbf,0xff740ff1,0xff2f0ff1,0xff0f94f1,0xff0ff1af,0xff14f10f,0xffeaf804,0xfff92a0f);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int value = (int) animation.getAnimatedValue();
                    img.setBackgroundColor(value);
                }
            });
            valueAnimator.setDuration(6000);
            valueAnimator.setEvaluator(new ArgbEvaluator());
            valueAnimator.start();
    

    效果:

    这里写图片描述


    源码:
    public class ArgbEvaluator implements TypeEvaluator {
        private static final ArgbEvaluator sInstance = new ArgbEvaluator();
        /**
         * @hide
         */
        public static ArgbEvaluator getInstance() {
            return sInstance;
        }
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            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))));
        }
    

    色值:A R G B ,分别表示透明度,红色,绿色,蓝色,每一个色值都用十六进制来表示,0xffff0000,

    色值是通过位移和运算求出的。色值和ARGB对应关系如下:

    这里写图片描述

    ofObject讲解

    ofObject()可以实现自定义类型的动画效果

    public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values);
    

    第一个是自定义的 Evaluator,第二个是可变长参数,Object 类型的


    一个小例子:

    这里写图片描述
    自定义Evaluator
    public class MyEvaluator implements TypeEvaluator<String> {
        private static final String TAG = "MyEvaluator";
        @Override
        public String evaluate(float fraction, String startValue, String endValue) {
            int length = endValue.length();
            String result = String.valueOf(endValue.charAt((int) (fraction * (length -1))));
            return result;
        }
    }
    
    ValueAnimator animator = ValueAnimator.ofObject(new MyEvaluator(),"且品鸡汤莫问厨娘");
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    String str = (String) animation.getAnimatedValue();
                    tv.setText(str);
                }
            });
            animator.setDuration(5000);
            animator.setInterpolator(new LinearInterpolator());
            animator.start();
    

    自定义对象实例


    效果图:

    这里写图片描述
     private void animatorOfObjectCustom(){
            ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(),new Ponit(20),new Ponit(200));
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    Ponit ponit = (Ponit) animation.getAnimatedValue();
                    mCircleView.setPoint(ponit);
                }
            });
            animator.setDuration(1000);
            animator.setInterpolator(new BounceInterpolator());
            animator.start();
        }
    

    自定义类

    public class Ponit {
        private int mRadius;
        public Ponit() {
        }
        public Ponit(int mRadius) {
            this.mRadius = mRadius;
        }
        public int getRadius() {
            return mRadius;
        }
        public void setRadius(int mRadius) {
            this.mRadius = mRadius;
        }
    }
    
    

    自定义view

    public class CircleView extends View {
        private Ponit mCurrentPoint;
        private Paint mPiant ;
        private int mScreenWidth;//屏幕宽度
        public CircleView(Context context) {
            this(context,null);
        }
    
        public CircleView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public CircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mPiant = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPiant.setColor(Color.RED);
            mPiant.setStyle(Paint.Style.FILL);
            mScreenWidth = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            if (mCurrentPoint != null){
                canvas.drawCircle(mScreenWidth/2,getY()+getPaddingTop(),mCurrentPoint.getRadius(),mPiant);
            }
        }
    
        public void setPoint(Ponit point){
            this.mCurrentPoint = point;
            invalidate();
        }
    }
    
    

    相关文章

      网友评论

          本文标题:ValueAnimator详解

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