天天看點

Android屬性動畫實作TextView類似支付寶餘額數字滾動

Demo下載下傳連結

項目中的小需求,完成類似于支付寶餘額的數字滾動效果,找了網上的一個小demo,再加上郭嬸的關于屬性動畫的文章,整理一部分代碼分享給有需要的人.

下面貼出封裝的TextView代碼片段,主要是利用屬性動畫來更新TextView完成數字滾動更新.

package shidong.com.numberscrolldemo.view;

import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;

import java.text.DecimalFormat;

import shidong.com.numberscrolldemo.R;

/**
 * NumberScrollTextView,用屬性動畫完成數字平滑滾動
 * created by shidong
 */
public class NumberScrollTextView extends TextView implements IRiseNumber {

    private static final int STOPPED = ;

    private static final int RUNNING = ;

    private int mPlayingState = STOPPED;

    private float number;

    private float fromNumber;

    /**
     * 預設時長
     */
    private long duration = ;
    /**
     * 1.int 2.float
     */
    private int numberType = ;

    private DecimalFormat fnum;

    private EndListener mEndListener = null;

    final static int[] sizeTable = {, , , , , , ,
            , , Integer.MAX_VALUE};

    /**
     * 構造方法
     *
     * @param context
     */
    public NumberScrollTextView(Context context) {
        super(context);
    }

    /**
     * 構造方法
     *
     * @param context
     * @param attr
     */
    public NumberScrollTextView(Context context, AttributeSet attr) {
        super(context, attr);
        setTextColor(context.getResources().getColor(R.color.black));
        setTextSize();
    }

    public NumberScrollTextView(Context context, AttributeSet attr, int defStyle) {
        super(context, attr, defStyle);
    }

    /**
     * 動畫是否正在執行
     *
     * @return
     */
    public boolean isRunning() {
        return (mPlayingState == RUNNING);
    }

    /**
     * 浮點型數字變動
     */
    private void runFloat() {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(fromNumber, number);
        valueAnimator.setDuration(duration);

        valueAnimator
                .addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator valueAnimator) {

                        setText(fnum.format(Float.parseFloat(valueAnimator
                                .getAnimatedValue().toString())));
                        if (valueAnimator.getAnimatedFraction() >= ) {
                            mPlayingState = STOPPED;
                            if (mEndListener != null)
                                mEndListener.onEndFinish();
                        }
                    }

                });

        valueAnimator.start();
    }

    /**
     * 整型數字變動
     */
    private void runInt() {

        ValueAnimator valueAnimator = ValueAnimator.ofInt((int) fromNumber,
                (int) number);
        valueAnimator.setDuration(duration);

        valueAnimator
                .addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator valueAnimator) {
                        setText(valueAnimator.getAnimatedValue().toString());
                        if (valueAnimator.getAnimatedFraction() >= ) {
                            mPlayingState = STOPPED;
                            if (mEndListener != null)
                                mEndListener.onEndFinish();
                        }
                    }
                });
        valueAnimator.start();
    }

    static int sizeOfInt(int x) {
        for (int i = ; ; i++) {
            if (x <= sizeTable[i])
                return i + ;
        }
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        fnum = new DecimalFormat("##0.00");
    }

    /**
     * 開始動畫
     */
    @Override
    public void start() {

        if (!isRunning()) {
            mPlayingState = RUNNING;
            if (numberType == )
                runInt();
            else
                runFloat();
        }
    }


    /**
     * 設定數字
     *
     * @param number
     */
    @Override
    public void withNumber(int number) {
        this.number = number;
        numberType = ;
        if (number > ) {
            fromNumber = number
                    - (float) Math.pow(, sizeOfInt((int) number) - );
        } else {
            fromNumber = number / ;
        }
    }

    /**
     * 設定數字
     *
     * @param number
     */
    @Override
    public void withNumber(float number) {

        this.number = number;
        numberType = ;
        if (number > ) {
            fromNumber = number
                    - (float) Math.pow(, sizeOfInt((int) number) - );
        } else {
            fromNumber = number / ;
        }

    }

    @Override
    public void setFromAndEndNumber(int fromNumber, int endNumber) {
        this.fromNumber = fromNumber;
        this.number = endNumber;
        numberType = ;
    }

    @Override
    public void setFromAndEndNumber(float fromNumber, float endNumber) {
        this.fromNumber = fromNumber;
        this.number = endNumber;
        numberType = ;
    }

    /**
     * 設定動畫時長
     */
    @Override
    public void setDuration(long duration) {
        this.duration = duration;
    }

    /**
     * 設定動畫結束監聽
     */
    @Override
    public void setOnEndListener(EndListener callback) {
        mEndListener = callback;
    }

    /**
     * 動畫結束接口
     */
    public interface EndListener {
        /**
         * 動畫結束
         */
        public void onEndFinish();
    }

}
           

主界面調用

package shidong.com.numberscrolldemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import shidong.com.numberscrolldemo.view.NumberScrollTextView;

/**
 * 主界面,數字平滑滾動
 * created by mashidong
 */
public class MainActivity extends AppCompatActivity {

    private NumberScrollTextView tv_number;
    private Button btn_start;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        tv_number = (NumberScrollTextView) findViewById(R.id.tv_number);
        tv_number.setFromAndEndNumber(, );
        tv_number.setDuration();
        btn_start = (Button) findViewById(R.id.btn_start);
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_number.start();
            }
        });
    }
}
           

Demo下載下傳

如果不熟悉屬性動畫,建議參考這篇文章http://blog.csdn.net/guolin_blog/article/details/43536355