android属性动画ValueAnimator详解

ValueAnimator:通过不断控制值的变化,在不断手动的赋给对象的属性,从而实现动画的效果
ValueAnimator 的常用方法:
ValueAnimator.ofInt(int values) ValueAnimator.ofFloat(float value) ValueAnimator.ofObject(int values)
废话不多哔哔 直接开始

ValueAnimator.ofInt(int values)的使用

首先看一下源码熟悉一下

 public static ValueAnimator ofInt(int... values) {
        ValueAnimator anim = new ValueAnimator();
        anim.setIntValues(values);
        return anim;
    }

源码很简单 就是将值赋给了ValueAnimator 这个对象
简单的demo:

     private Button btn;
     private ValueAnimator valueAnimator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animator_text);
        btn = findViewById(R.id.haha);
        valueAnimator = ValueAnimator.ofInt(btn.getLayoutParams().width,300);
        valueAnimator.setDuration(1500);//时间时长

        // 设置动画延迟播放时间
        valueAnimator.setStartDelay(500);

        // 设置动画重复播放次数 = 重放次数+1
        // 动画播放次数 = infinite时,动画无限重复
        valueAnimator.setRepeatCount(2);

        // 设置重复播放动画模式
        // ValueAnimator.RESTART(默认):正序重放
        // ValueAnimator.REVERSE:倒序回放
        valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
       
        // 数值每次变化更新都会调用该方法
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animator) {

                int currentValue = (Integer) animator.getAnimatedValue();
                // 获得每次变化后的属性值
               

                btn.getLayoutParams().width = currentValue;
                // 每次值变化时,将值手动赋值给对象的属性
               

             // 步骤4:刷新视图,即重新绘制,从而实现动画效果
                btn.requestLayout();

            }
        });

        valueAnimator.start();
        // 启动动画



    }

layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AnimatorText">

    <Button
        android:id="@+id/haha"
        android:layout_width="80dp"
        android:layout_height="50dp"
        android:layout_centerInParent="true"
        android:text="哈哈"
        />
</RelativeLayout>

ValueAnimator.ofFloat() 和ofInt()使用方法相似 在这里就不多做使用
然后直接上本次的重点 ValueAnimator.ofObject();
同样的 我们先来看一下源码:

 public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
        ValueAnimator anim = new ValueAnimator();
        anim.setObjectValues(values);
        anim.setEvaluator(evaluator);
        return anim;
    }

其中的第一个参数为TypeEvaluator(估值器):数值具体变化过程的当前数值
然后我们看一下估值器的源码:

public interface TypeEvaluator<T> { 
     //fraction -> 从开始到结束的分数(占比)
     //startValue ->起始值
     //endValue  ->结束值
    public T evaluate(float fraction, T startValue, T endValue);
}

也很简单 就是一个接口 里面有一个方法
要想使用ValueAnimator.ofObject()我们就需要实现TypeEvaluator的接口
这就要根据你的业务需求进行设置,这里就上一个demo:(TypeEvaluator的实现类重写的方法中需要传的都是对象 而不是数值 )
1.Point类:

public class Point {

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }
        private float x;

        private float y;

        public float getX() {
            return x;
        }

        public float getY() {
            return y;
        }


}

2.定义PointEvaluator类实现TypeEvaluator接口

public class PointEvaluator implements TypeEvaluator {
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        Point start = (Point) startValue;
        Point end = (Point) endValue;

        float x = start.getX() + fraction * (end.getX() - start.getX());
        float y = start.getY() + fraction * (end.getY() - start.getY());
        Point point  = new Point(x,y);
        return point;
    }
}

3.简单的实现:

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

4.自当以View实现小球下滑功能

public class TryText extends View {
    public static final float RADIUS = 50f;

    private Point currentPoint;

    private Paint mPaint;

    public TryText(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);
        Log.i("haonanguo","@"+getWidth());
        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();
    }

}

效果图:
在这里插入图片描述
这里也很简单 确定好起始值和结束值后 然后调用invalidate一直改变小球的坐标就ok
关于TypeEvaluator 也可以去参考FloatEvaluator的源码以及IntEvaluator的源码

发布了43 篇原创文章 · 获赞 60 · 访问量 6753

猜你喜欢

转载自blog.csdn.net/yuhang01/article/details/103241766