天天看点

自定义数字滚动动画的TextView

背景

在开发需求当中,当有总收益、总用户数等数字要显示时,为了更好的给用户提供展示效果,往往会想加入炫酷的数字滚动动画,使呆板平静的数字变得灵活起来,给人一种增值的直观感受。

简介

NumberRollingView

是一个自定义的自带数字滚动动画的

TextView

,通过使用

setContent(String str)

方法进行数字字符串设置,传入相应的金额数字字符串(如

"9686.86"

)或者整数数字字符串(如

"968"

),设置的数字必须是正数。当显示页面初始化完成的过程中,就可以看到数字滚动的效果了。

效果图:

自定义数字滚动动画的TextView

使用

1.在

attr.xml

中配置

NumberRollingView

的自定义属性

<declare-styleable name="NumberRollingView">
    <!--帧数-->
    <attr name="frameNum" format="integer"></attr>
    <!--内容的格式-->
    <attr name="textType">
        <enum name="money" value="0"></enum>
        <enum name="num" value="1"></enum>
    </attr>
    <!--是否设置每三位数字一个逗号-->
    <attr name="useCommaFormat" format="boolean"></attr>
    <!--是否当内容改变的时候使用动画,反之则不使用动画-->
    <attr name="runWhenChange" format="boolean"></attr>
</declare-styleable>
           

frameNum

:动画的帧数,默认为

30

帧;

textType

:内容的格式,有

money

(金额、两位小数)和

num

(整数)两种格式,默认为

(金额格式);

useCommaFormat

:是否设置每三位数字一个逗号,默认为

true

(设置逗号显示);

runWhenChange

:是否当内容改变的时候使用动画,反之则不使用动画,默认为

true

(内容改变时使用动画);

2.在

XML

布局文件中引用

View

<com.wiggins.digitalchange.widget.NumberRollingView
    android:id="@+id/tv_money"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="0.00"
    android:textColor="@color/white"
    android:textSize="@dimen/font_max"
    android:textStyle="bold" />

<com.wiggins.digitalchange.widget.NumberRollingView
    android:id="@+id/tv_num"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="0"
    android:textColor="@color/white"
    android:textSize="@dimen/font_max"
    android:textStyle="bold"
    app:textType="num" />
           

前者是金额数字

View

,后者是整数数字

View

3.

Java

文件中调用

tvMoney.setContent("9686.86");
tvNum.setContent("9686");
           

4.取消数字的自动格式化(设置每三位数字一个逗号)

默认情况下显示的数字经过了格式化处理,设置每三位数字添加一个逗号分隔,这使得数字看起来清晰明了,不会显得臃肿繁杂。如果不想将数字进行格式化处理,可以在布局文件中将

useCommaFormat

属性设置为

false

,或者在代码中设置

setUseCommaFormat(boolean useCommaFormat)

false

,这样显示的数字就不会是带有逗号了。

5.设置无论内容是否改变都要执行滚动动画

默认情况下

NumberRollingView

会自动判断传入的内容是否有变化,当内容发生变化时执行数字滚动动画,内容未变时不执行数字滚动动画。如果想无论内容是否有变化都要执行滚动动画的话,可以在布局文件中将

runWhenChange

属性设置为

false

,或者在代码中设置

setRunWhenChange(boolean runWhenChange)

false

,这样无论内容是否有变化都会执行滚动动画。

6.设置动画帧数

默认情况下数字滚动动画帧数为

30

帧,如果需要修改动画帧数,可根据实际需要在在布局文件中将

frameNum

属性设置为自己想要的帧数,或者在代码中设置

setFrameNum(int frameNum)

为自己想要的帧数即可。

7.数字字符串格式化(每三位数字添加一个逗号)

/**
 * @param str       字符串只能为两位小数或者整数
 * @param isDecimal 是否是小数
 * @Description 格式化字符串,每三位用逗号隔开
 */
public static String addComma(String str, boolean isDecimal) {
    //先将字符串颠倒顺序
    str = new StringBuilder(str).reverse().toString();
    if (str.equals("0")) {
        return str;
    }
    String str2 = "";
    for (int i = ; i < str.length(); i++) {
        if (i *  +  > str.length()) {
            str2 += str.substring(i * , str.length());
            break;
        }
        str2 += str.substring(i * , i *  + ) + ",";
    }
    if (str2.endsWith(",")) {
        str2 = str2.substring(, str2.length() - );
    }
    //最后再将顺序反转过来
    String temp = new StringBuilder(str2).reverse().toString();
    if (isDecimal) {
        //去掉最后的","
        return temp.substring(, temp.lastIndexOf(",")) + temp.substring(temp.lastIndexOf(",") + , temp.length());
    } else {
        return temp;
    }
}
           

8.开始金额数字动画的方法

如果传入的金额中包含格式化的字符如

","

"-"

符号,就将符号去除;将传入的数字进行格式转换,转换为

Double

类型的金额格式,如果发生转换异常则直接进行显示;同时判断传入的数字大小,如果为

则直接显示,若不为

则设置每帧间隔的大小,发送

Message

消息给

Handler

进行内容的更新。

/**
 * @Description 开始金额数字动画的方法
 */
public void startMoneyAnim(String moneyStr) {
    // 如果传入的数字已经格式化了,则将包含的符号去除
    String money = moneyStr.replace(",", "").replace("-", "");
    try {
        finalMoneyNum = Double.parseDouble(money);
        if (finalMoneyNum == ) {
            // 如果传入的数字为0则直接使用setText()进行显示
            NumberRollingView.this.setText(moneyStr);
            return;
        }
        nowMoneyNum = ;
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                Message msg = handler.obtainMessage();
                // 将传入的数字除以帧数,得到每帧间隔的大小
                double size = finalMoneyNum / frameNum;
                msg.what = MONEY_TYPE;
                // 如果每帧的间隔小于0.01,则设置间隔为0.01
                msg.obj = size <  ?  : size;
                // 发送消息改变UI
                handler.sendMessage(msg);
            }
        });
    } catch (NumberFormatException e) {
        e.printStackTrace();
        //如果转换Double失败则直接用setText()
        NumberRollingView.this.setText(moneyStr);
    }
}
           

9.开始数字动画的方法

同上述金额数字一般,先进行格式化符号去除,然后进行类型转换,将其转换为

Integer

类型的整数格式,如果发生转换异常则直接进行显示;为了更加人性化,我们将传入的数字与帧数作了比较,如果数值小于帧数就直接显示,当然你想不管数字大小都能进行动画展示,只需将下面的帧数间隔的获取稍加改造即可;若大于等于设置的帧数则设置每帧间隔的大小,发送

Message

消息给

Handler

进行内容的更新。

/**
 * @Description 开始数字动画的方法
 */
public void startNumAnim(String numStr) {
    // 如果传入的数字已经格式化了,则将包含的符号去除
    String num = numStr.replace(",", "").replace("-", "");
    try {
        finalNum = Integer.parseInt(num);
        if (finalNum < frameNum) {
            // 如果传入的数字比帧数小,则直接使用setText()
            NumberRollingView.this.setText(numStr);
            return;
        }
        // 默认从0开始动画
        nowNum = ;
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                Message msg = handler.obtainMessage();
                // 将传入的数字除以帧数,得到每帧间隔的大小
                int temp = finalNum / frameNum;
                msg.what = NUM_TYPE;
                msg.obj = temp;
                // 发送消息改变UI
                handler.sendMessage(msg);
            }
        });
    } catch (NumberFormatException e) {
        e.printStackTrace();
        //如果转换Integer失败则直接用setText
        NumberRollingView.this.setText(numStr);
    }
}
           

项目地址 ☞ 传送门

继续阅读