美文网首页
android动画学习(5)- Property Animati

android动画学习(5)- Property Animati

作者: 墨源为水 | 来源:发表于2016-06-19 15:14 被阅读69次

    在上一篇文章已经讲过属性动画的工作步骤如下:

    Property Animation动画有两个步聚:
    1.计算属性值
    2.为目标对象的属性设置属性值,即应用和刷新动画

    1.计算属性值

    以下分析引入了两个概念:已完成动画分数(elapsed fraction)、插值分数( interpolated fraction )。

    属性值计算
    (1)过程一:计算已完成动画分数 elapsed fraction
    为了执行一个动画,你需要创建一个ValueAnimator,并且指定目标对象属性的开始、结束值和持续时间。在调用start后的整个动画过程中, ValueAnimator会根据已经完成的动画时间计算得到一个0到1之间的分数,代表该动画的已完成动画百分比。0表示0%,1表示100%。
    (2)过程二:计算插值(动画变化率)interpolated fraction
    当ValueAnimator计算完已完成动画分数后,它会调用当前设置的TimeInterpolator,去计算得到一个interpolated(插值)分数,在计算过程中,已完成动画百分比会被加入到新的插值计算中。
    (3)过程三:计算属性值
    当插值分数计算完成后,ValueAnimator 会根据插值分数调用合适的 TypeEvaluator去计算运动中的属性值。
    TimeInterpolator和TypeEvaluator的区别
    首先明确动画属性值的计算包括三步,其中第二步和第三步分别需要借助TimeInterpolator和TypeEvluator完成。TypeEvaluator所做的是根据数据结构计算最终的属性值,允许你定义自己的数据结构,这是官方对它的真正定义,如果你所定义的属性值的数据类型不是float、int、color类型,那么你需要实现TypeEvaluator接口的evaluate()方法,自己进行属性值的计算Interpolator更倾向于你定义一种运动的变化率,比如匀速、加速、减速等。

    1.1Interpolators类

    就是插值器,详细的情况之前一片文章介绍了,Tween动画的插值器同样适用于属性动画。在这里不细讲。设置就是 anim.setInterpolator(new AccelerateInterpolator(2f));

    1.2 TypeEvaluator类

    这个类的作用简单来说,就是告诉动画系统如何从初始值过渡到结束值。它们通过Animator提供的动画的起始和结束值去计算一个动画的属性值。属性系统提供了以下几种Evaluators:

    1. IntEvaluator
    • FloatEvaluator
    • ArgbEvaluator
      这三个由系统提供,分别用于计算int,float,color型(十六进制)属性的计算器
    • TypeEvaluator
      一个用于用户自定义计算器的接口,如果你的对象属性值类型,不是int,float,或者color类型,你必须实现这个接口,去定义自己的数据类型。TypeEvaluator接口只有一个方法,就是evaluate()方法,它允许你使用的animator返回一个当前动画点的属性值。

    ValueAnimator.ofFloat()方法就是实现了初始值与结束值之间的平滑过度,那么这个平滑过度是怎么做到的呢?其实就是系统内置了一个FloatEvaluator,它通过计算告知动画系统如何从初始值过度到结束值,我们来看一下FloatEvaluator的代码实现:

    public class FloatEvaluator implements TypeEvaluator {  
        public Object evaluate(float fraction, Object startValue, Object endValue) {  
            float startFloat = ((Number) startValue).floatValue();  
            return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);  
        }  
    }  
    
    代码分析:

    很明显FloatEvaluator 是实现了TypeEvaluator 接口,重写evaluate()方法。evaluate()方法当中传入了三个参数,第一个参数fraction非常重要,这个参数用于表示动画的完成度的,我们应该根据它来计算当前动画的值应该是多少,第二第三个参数分别表示动画的初始值和结束值。知道这些参数含义,那以上代码就容易看懂的多。

    1.2.1那如何实现自定义TypeEvaluator

    eg.需求:实现屏幕上的一个点到另一个点的平滑过渡

    1.定义自定义POJO类
    public class Point {
        private float x;
        private float y;
        public Point(float x, float y) {
            this.x = x;
            this.y = y;
        }
        public float getX() {
            return x;
        }
        public float getY() {
            return y;
        }
    }
    

    就是用来屏幕上的某一点有x,y属性

    2.定义自定义TypeEvaluator
    public class PointEvaluator implements TypeEvaluator{
        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            Point startPoint = (Point) startValue;
            Point endPoint = (Point) endValue;
            float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
            float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
            Point point = new Point(x, y);
            return point;
        }
    }
    

    也可以这么写

    public class PointEvaluator implements TypeEvaluator<Point>{
        @Override
        public Point evaluate(float fraction, Point startValue, Point endValue) {
            Point startPoint = startValue;
            Point endPoint = endValue;
            float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
            float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
            Point point = new Point(x, y);
            return point;
        }
    }
    
    3.使用自定义TypeEvaluator

    3.1简单使用:

    Point point1 = new Point(0, 0);  
    Point point2 = new Point(300, 300);  
    ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), point1, point2);  
    anim.setDuration(5000);  
    anim.start();  
    

    3.2拓展使用
    实现一个圆形图从视图左上侧对角平滑到视图右下侧的自定义视图

    public class MyAnimView extends View {
        public static final float RADIUS = 50f;
    
        private Point currentPoint;
    
        private Paint mPaint;
    
        public MyAnimView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setColor(Color.BLUE);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            if (currentPoint == null) {
                currentPoint = new Point(RADIUS, RADIUS);
                drawCircle(canvas);
                startAnimation();
            } else {
                drawCircle(canvas);
            }
        }
    
        private void drawCircle(Canvas canvas) {
            float x = currentPoint.getX();
            float y = currentPoint.getY();
            canvas.drawCircle(x, y, RADIUS, mPaint);
        }
    
        private void startAnimation() {
            Point startPoint = new Point(RADIUS, RADIUS);
            Point endPoint = new Point(getWidth() - RADIUS, getHeight() - RADIUS);
            ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    currentPoint = (Point) animation.getAnimatedValue();
                    invalidate();
                }
            });
            anim.setDuration(5000);
            anim.start();
        }
    
    }
    

    相关文章

      网友评论

          本文标题:android动画学习(5)- Property Animati

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