Android属性动画ValueAnimator快速上手

来源:互联网 发布:11年体测数据 编辑:程序博客网 时间:2024/06/07 15:57

用处及部分原理

Android在API11中新增ValueAnimator类用于实现更多屌炸天的动画效果,其主要核心逻辑在于:
根据开发者设置的动画总时间调用Interpolator取得一个动画执行的效率值A,再调用TypeEvaluator中的evaluate方法传入值A返回计算出来需要参与到动画中的值B,再将动画值B传入AnimatorUpdateListener中的onAnimationUpdate方法中操作对象进行动画(此处可以不是动画)

从何入手

上面说了,一共有三个步骤,分别调用到了三个类(接口),现在分别看看三个不同的类的用法:


  • Interpolator——用于控制动画效率
    这里可以调用现有的几个实现类:
    • AccelerateDecelerateInterpolator:两头帮紧,中间孬松。就是中间快,开始和结束的时候慢
    • AccelerateInterpolator :开始慢,后来快
    • AnticipateInterpolator:先往后退一点再往前
    • AnticipateOvershootInterpolator:先退一点再往前再超过终点再退后
    • BounceInterpolator:最后弹一下
    • CycleInterpolator:动画循环播放特定的次数,速率改变沿着正弦曲线
    • DecelerateInterpolator:先快后慢
    • LinearInterpolator:匀速
    • OvershootInterpolator:超过终点再回来

如果这些还不能满足需求,那么自己去实现一个类,它会让你重写getInterpolation方法,这里入参是一个float类型,这个float由ValueAnimator计算并传入,传入时是匀速从0增长到1的,根据这个值就可以带入计算后再返回其他的值了,需要注意的是要控制计算后的值也应该是由0最后到1的,中间可以到2,也可以是-1,但是最终结果最好是1,这样有利于之后的调用。需要用到曾经学过的很多数学知识了,什么赛赢,阔赛赢,谭建提,阔谭建提之类的,再厉害点的可以加入Log,椭圆,双曲线等等,虽然很难,但是如果你执意要做,我也只能说厉害了,我的哥。


  • TypeEvaluator——计算产生动画需要的值
    这个东西需要自己去实现它,并重写evaluate方法,该方法入参float fraction, Object startValue, Object endValue,这里这个fraction就是上面Interpolator计算出来的值了。startValue和endValue就是起始值了,这里是Object,那代表这里的值可以是任何自定义类型,可以自己写一个Java类来进行数据包装,也可以传一个HashMap,都是可以的。然后在这个方法里面进行计算之后,再返回一个Object类型的值,也可以是返回任何值。

  • AnimatorUpdateListener——根据值进行动画
    这里是最后一步了。上面TypeEvaluator计算好的值会被传入到这里的onAnimationUpdate方法中,但是这里并不是直接传进来的Object,而是传入的ValueAnimator对象,可以使用ValueAnimator.getAnimaterdValue()方法获取到刚才计算出来的Object对象,然后进行动画变换。也可以不是动画,反正这里都已经取到值了,这个值能够拿来做的事情就多了去了。

为何不用Handler

额,自己体会吧。

一个DEMO

ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(),startValue,endValue);animator.addUpdateListener(new MyUpdateListener(view));animator.setInterpolator(new AccelerateInterpolator());animator.setDuration(2000);animator.start();class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {        View v;        public MyUpdateListener(View v) {            this.v = v;        }        @Override        public void onAnimationUpdate(ValueAnimator valueAnimator) {            PointF point = (PointF) valueAnimator.getAnimatedValue();            LayoutParams params = (LayoutParams) v.getLayoutParams();            params.setMargins((int) point.x, (int) point.y + paddingTop, 0, 0);            v.setLayoutParams(params);        }    }class PointEvaluator implements TypeEvaluator {        @Override        public Object evaluate(float fraction, Object startValue, Object endValue) {            PointF start = (PointF) startValue;            PointF end = (PointF) endValue;            float y = start.y + fraction * (end.y - start.y);            return new PointF(start.x, y);        }    }

上面就是一个加速下落的动画,如果要变成弧线,可以这样写一个TypeEvaluator:

class PointEvaluator implements TypeEvaluator {        @Override        public Object evaluate(float fraction, Object startValue, Object endValue) {            PointF start = (PointF) startValue;            PointF end = (PointF) endValue;            float x = start.x + fraction * (end.x - start.x);            float width = end.x - start.x;            if (width < 0) {                width *= -1;            }            float circleX = fraction * width;            float y = (float) ((2 * width - Math.sqrt(Math.pow((2 * (double) width), 2) - 4 * Math.pow((double) circleX, 2))) / 2);//这里取的四分之一个圆的弧线            return new PointF(y, x);        }    }

还有一个ofInt的方法,这个方法只需要传入开始的值和结束的值即可,在UpdateListener的那里getValue出来的时候强制转换成int来使用,相当于这里它里面有一个默认的TypeEvaluator了,其他都是相同的,不赘述了。

最后

在仔细阅读本文之后,试着去写一个小demo,相信你就能够明白ValueAnimator的运行原理了。当你成为一个old driver的时候再回来看这个文章,你也能够轻轻松松的自己实现一个ValueAnimator的类了。

1 0
原创粉丝点击