«

Android之增长的数字(仿支付宝资产数字)

时间:2024-3-2 19:00     作者:韩俊     分类: Android


今天我们自定义一个TextView,它的名称叫做RiseNumberTextView,我们在平时使用支付宝的时候会发现进入资产页面的时候,资产数据会从一个数一直不停的增长直至你的真实数据然后停止。


那么这个效果是如何做到的呢?首先来看一下我们做出的效果图,然后我们一起来实现它。




这里面会用到一个核心的类:ValueAnimatr这是一个android属性动画


按照面向接口编程的好习惯,首先定义一个接口:

/**
 * 增长的数字接口
 * 
 */
public interface IRiseNumber {
    /**
     * 开始播放动画的方法
     */
    public void start();

    /**
     * 设置小数
     * 
     * @param number
     * @return
     */
    public void withNumber(float number);

    /**
     * 设置整数
     * 
     * @param number
     * @return
     */
    public void withNumber(int number);

    /**
     * 设置动画播放时长
     * 
     * @param duration
     * @return
     */
    public void setDuration(long duration);

    /**
     * 设置动画结束监听器
     * 
     * @param callback
     */
    public void setOnEndListener(RiseNumberTextView.EndListener callback);
}


然后自定义view------数字增长TextView,内容如下:

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

import com.bear.risenumber.R;
import com.nineoldandroids.animation.ValueAnimator;

import java.text.DecimalFormat;

/**
 * 自定义RiseNumberTextView继承TextView,并实现接口RiseNumberBase
 * 
 */
public class RiseNumberTextView 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 = 1500;
    /**
     * 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 RiseNumberTextView(Context context) {
        super(context);
    }

    /**
     * 使用xml布局文件默认的被调用的构造方法
     * 
     * @param context
     * @param attr
     */
    public RiseNumberTextView(Context context, AttributeSet attr) {
        super(context, attr);
        setTextColor(context.getResources().getColor(R.color.rise_number_text_color_red));
        setTextSize(30);
    }

    public RiseNumberTextView(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();
        }
    }

    /**
     * 设置一个小数进来
     */
    @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 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;
        }

    }

    /**
     * 设置动画播放时间
     */
    @Override
    public void setDuration(long duration) {
        this.duration = duration;
    }

    /**
     * 设置动画结束监听器
     */
    @Override
    public void setOnEndListener(EndListener callback) {
        mEndListener = callback;
    }

    /**
     * 定义动画结束接口
     * 
     * 
     */
    public interface EndListener {
        /**
         * 当动画播放结束时的回调方法
         */
        public void onEndFinish();
    }

}

然后在Activity中去使用自定义的view:

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.bear.risenumber.views.RiseNumberTextView;
import com.bear.risenumber.views.RiseNumberTextView.EndListener;

public class MainActivity extends Activity {

    private RiseNumberTextView rnTextView;

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

    }

    private void setupViews() {
        // 获取到RiseNumberTextView对象
        rnTextView = (RiseNumberTextView) findViewById(R.id.risenumber_textview);
        // 设置数据
        rnTextView.withNumber(2666.50f);
        // 设置动画播放时间
        rnTextView.setDuration(5000);
        // 监听动画播放结束
        rnTextView.setOnEndListener(new EndListener() {

            @Override
            public void onEndFinish() {
                Toast.makeText(MainActivity.this, "数据增长完毕...",
                        Toast.LENGTH_SHORT).show();
            }
        });

        Button btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if(rnTextView.isRunning()){
                    Toast.makeText(MainActivity.this, "数字还没增长完,请稍候尝试...", Toast.LENGTH_SHORT).show();
                }else{
                    // 开始播放动画
                    rnTextView.start();
                }

            }
        });
    }
}


附上示例源码,有兴趣的可以下载导入到Eclipse中去运行以下:

Android Rise Number TextView


标签: android

热门推荐