android属性动画ValueAnimator详解

本文详细介绍了Android属性动画中的ValueAnimator,包括ValueAnimator.ofInt()的使用方法,通过不断改变对象属性值来实现动画效果。文章通过源码分析和示例代码,展示了如何利用ValueAnimator.ofObject()配合TypeEvaluator实现自定义动画,比如小球下滑功能。同时,建议读者可以参考FloatEvaluator和IntEvaluator的源码以进一步理解TypeEvaluator的工作原理。
摘要由CSDN通过智能技术生成

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的源码

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安东尼肉店

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值