天天看點

自定義數字滾動動畫的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);
    }
}
           

項目位址 ☞ 傳送門

繼續閱讀