1. 程式人生 > >Android屬性動畫實現TextView類似支付寶餘額數字滾動

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 = 0; private static final int RUNNING = 1; private
int mPlayingState = STOPPED; private float number; private float fromNumber; /** * 預設時長 */ private long duration = 1000; /** * 1.int 2.float */ private int numberType = 2; private DecimalFormat fnum; private EndListener mEndListener = null; final
static int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, 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(30); } 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() >= 1) { 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() >= 1) { mPlayingState = STOPPED; if (mEndListener != null) mEndListener.onEndFinish(); } } }); valueAnimator.start(); } static int sizeOfInt(int x) { for (int i = 0; ; i++) { if (x <= sizeTable[i]) return i + 1; } } @Override protected void onFinishInflate() { super.onFinishInflate(); fnum = new DecimalFormat("##0.00"); } /** * 開始動畫 */ @Override public void start() { if (!isRunning()) { mPlayingState = RUNNING; if (numberType == 1) runInt(); else runFloat(); } } /** * 設定數字 * * @param number */ @Override public void withNumber(int number) { this.number = number; numberType = 1; if (number > 1000) { fromNumber = number - (float) Math.pow(10, sizeOfInt((int) number) - 2); } else { fromNumber = number / 2; } } /** * 設定數字 * * @param number */ @Override public void withNumber(float number) { this.number = number; numberType = 2; if (number > 1000) { fromNumber = number - (float) Math.pow(10, sizeOfInt((int) number) - 1); } else { fromNumber = number / 2; } } @Override public void setFromAndEndNumber(int fromNumber, int endNumber) { this.fromNumber = fromNumber; this.number = endNumber; numberType = 1; } @Override public void setFromAndEndNumber(float fromNumber, float endNumber) { this.fromNumber = fromNumber; this.number = endNumber; numberType = 2; } /** * 設定動畫時長 */ @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(0, 20000);
        tv_number.setDuration(1000);
        btn_start = (Button) findViewById(R.id.btn_start);
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_number.start();
            }
        });
    }
}