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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章