背景
在開發需求當中,當有總收益、總使用者數等數字要顯示時,為了更好的給使用者提供展示效果,往往會想加入炫酷的數字滾動動畫,使呆闆平靜的數字變得靈活起來,給人一種增值的直覺感受。
簡介
NumberRollingView
是一個自定義的自帶數字滾動動畫的
TextView
,通過使用
setContent(String str)
方法進行數字字元串設定,傳入相應的金額數字字元串(如
"9686.86"
)或者整數數字字元串(如
"968"
),設定的數字必須是正數。當顯示頁面初始化完成的過程中,就可以看到數字滾動的效果了。
效果圖:
使用
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);
}
}
項目位址 ☞ 傳送門