ValueAnimator详解

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();
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容

  • 1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让全面说说Android的动画,所以今...
    未聞椛洺阅读 2,709评论 0 10
  • Animation Animation类是所有动画(scale、alpha、translate、rotate)的基...
    四月一号阅读 1,916评论 0 10
  • 深夜手机突然响起,本已睡着的我,出于好奇,又担心哪个傻瓜半夜哭泣需要我,于是顶着全天拼搏脑袋高速运转后疲惫的干尸,...
    郑桂煌阅读 597评论 0 0
  • 没有什么比心灵开放更重要。 学会培养更宏大的三观,学会不嫉妒而是合作,学会不评判而是理解,学会不挑刺而是欣赏。不要...
    唐璟宣阅读 268评论 0 0
  • 在二零一七年二月十八日的晚上,我们看了一部飞机有关电影,这部电影的名字叫萨利机长。 算利息涨这部电影,讲了一个跟飞...
    神了天阅读 340评论 1 1