NumberRunningTextView.java 8.4 KB
Newer Older
C
chaychan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
package com.chaychan.viewlib;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;

import com.chaychan.viewlib.utils.StringUtils;

import java.text.DecimalFormat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 数字滚动的textView
 */
public class NumberRunningTextView extends TextView {

    private static final int MONEY_TYPE = 0;
    private static final int NUM_TYPE = 1;

    private int frameNum;// 总共跳跃的帧数,默认30跳
    private int textType;//内容的类型,默认是金钱类型
    private boolean useCommaFormat;//是否使用每三位数字一个逗号的格式,让数字显得比较好看,默认使用
    private boolean runWhenChange;//是否当内容有改变才使用动画,默认是

    private ExecutorService threadPool = Executors.newFixedThreadPool(1);// 1个线程的线程池;
    private DecimalFormat formatter = new DecimalFormat("0.00");// 格式化金额,保留两位小数

    private double nowMoneyNum = 0.00;// 记录每帧增加后的金额数字
    private double finalMoneyNum;// 目标金额数字(最终的金额数字)

    private int nowNum;//记录每帧增加后的数字
    private int finalNum;//目标数字(最终的数字)
    private String preStr;

    public NumberRunningTextView(Context context) {
        this(context, null);
    }

    public NumberRunningTextView(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.textViewStyle);
    }

    public NumberRunningTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.NumberRunningTextView);
        frameNum = ta.getInt(R.styleable.NumberRunningTextView_frameNum, 30);
        textType = ta.getInt(R.styleable.NumberRunningTextView_textType, MONEY_TYPE);
        useCommaFormat = ta.getBoolean(R.styleable.NumberRunningTextView_useCommaFormat, true);
        runWhenChange = ta.getBoolean(R.styleable.NumberRunningTextView_runWhenChange,true);
    }


    /**
     * 设置需要滚动的金钱(必须为正数)或整数(必须为正数)的字符串
     *
     * @param str
     */
    public void setContent(String str) {
        //如果是当内容改变的时候才执行滚动动画,判断内容是否有变化
        if (runWhenChange){
            if (TextUtils.isEmpty(preStr)){
                //如果上一次的str为空
                preStr = str;
                useAnimByType(str);
                return;
            }

            //如果上一次的str不为空,判断两次内容是否一致
            if (preStr.equals(str)){
                //如果两次内容一致,则不做处理
                return;
            }

            preStr = str;//如果两次内容不一致,记录最新的str
        }

        useAnimByType(str);
    }

    private void useAnimByType(String str) {
        if (textType == MONEY_TYPE) {
            playMoneyAnim(str);
        } else {
            playNumAnim(str);
        }
    }


    /**
     * 播放金钱数字动画的方法
     *
     * @param moneyStr
     */
    public void playMoneyAnim(String moneyStr) {
        String money = moneyStr.replace(",", "").replace("-", "");//如果传入的数字已经是使用逗号格式化过的,或者含有符号,去除逗号和负号
        try {
            finalMoneyNum = Double.parseDouble(money);
            if (finalMoneyNum == 0) {
                //如果传入的为0,则直接使用setText()
                NumberRunningTextView.this.setText(moneyStr);
                return;
            }
            nowMoneyNum = 0;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    Message msg = handler.obtainMessage();
                    double size = finalMoneyNum / frameNum;//数字除以帧数,得到每帧跳跃的大小
                    msg.what = MONEY_TYPE;
                    msg.obj = size < 0.01 ? 0.01 : size;// 如果每帧的间隔比0.01小,就设置为0.01
                    handler.sendMessage(msg);// 发送通知改变UI
                }
            });

        } catch (NumberFormatException e) {
            e.printStackTrace();
            NumberRunningTextView.this.setText(moneyStr);//如果转换Double失败则直接用setText
        }
    }

    /**
     * 播放数字动画的方法
     *
     * @param numStr
     */
    public void playNumAnim(String numStr) {
        String num = numStr.replace(",", "").replace("-", "");//如果传入的数字已经是使用逗号格式化过的,或者含有符号,去除逗号和负号
        try {
            finalNum = Integer.parseInt(num);
            if (finalNum < frameNum) {
                //由于是整数,每次是递增1,所以如果传入的数字比帧数小,则直接使用setText()
                NumberRunningTextView.this.setText(numStr);
                return;
            }
            nowNum = 0;// 默认都是从0开始动画
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    Message msg = handler.obtainMessage();
                    int temp = finalNum / frameNum;//数字除以帧数,得到每帧跳跃的大小
                    msg.what = NUM_TYPE;
                    msg.obj = temp;
                    handler.sendMessage(msg);// 发送通知改变UI
                }
            });

        } catch (NumberFormatException e) {
            e.printStackTrace();
            NumberRunningTextView.this.setText(numStr);//如果转换Double失败则直接用setText
        }
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MONEY_TYPE://金钱数字的滚动
                    String str = formatter.format(nowMoneyNum).toString();//保留两位小数的字符串

                    // 更新显示的内容
                    if (useCommaFormat) {
                        //使用每三位数字一个逗号的格式
                        String formatStr = StringUtils.addComma(str);//三位一个逗号格式的字符串
                        NumberRunningTextView.this.setText(formatStr);
                    } else {
                        NumberRunningTextView.this.setText(str);
                    }

                    nowMoneyNum += (double) msg.obj;//记录当前每帧递增后的数字

                    if (nowMoneyNum < finalMoneyNum) {
                        //如果当前记录的金额数字小于目标金额数字,即还没达到目标金额数字,继续递增
                        Message msg2 = handler.obtainMessage();
                        msg2.what = MONEY_TYPE;
                        msg2.obj = msg.obj;
                        handler.sendMessage(msg2);// 继续发送通知改变UI
                    } else {
                        //已经达到目标的金额数字,显示最终的数字
                        if (useCommaFormat) {
                            NumberRunningTextView.this.setText(StringUtils.addComma(formatter.format(finalMoneyNum)));
                        } else {
                            NumberRunningTextView.this.setText(formatter.format(finalMoneyNum));
                        }
                    }
                    break;

                case NUM_TYPE://普通数字滚动
                    NumberRunningTextView.this.setText(String.valueOf(nowNum));
                    nowNum += (Integer) msg.obj;//记录当前每帧递增后的数字
                    if (nowNum < finalNum) {
                        //如果当前记录的数字小于目标数字,即还没达到目标数字,继续递增
                        Message msg2 = handler.obtainMessage();
                        msg2.what = NUM_TYPE;
                        msg2.obj = msg.obj;
                        handler.sendMessage(msg2);// 继续发送通知改变UI
                    } else {
                        //已经达到目标的数字,显示最终的内容
                        NumberRunningTextView.this.setText(String.valueOf(finalNum));
                    }
                    break;
            }
        }
    };
}