1. 程式人生 > >自定義View實現自動數字增長的TextView

自定義View實現自動數字增長的TextView

用過理財工具的對軟體裡會自動增長的TextView都不會陌生,這種動效會讓你有一種money無限多的趕腳,這種特效可不可以模仿呢?今天通過一個自定義的TextView來模仿一下。

首先定義一個介面,制定一下規則:

public interface IRaiseNumber {

void start();
   void setFloat(float fromNum, float toNum);
   void setInteger(int fromNum, int toNum);
   void setDuration(long duration);
   void setOnEndListener
(RiseNumberTextView.EndListener callback);
}

自定義TextView程式碼如下:

public class RiseNumberTextView extends TextView implements IRaiseNumber {

private static final int STOPPED = 0;
   private static final int RUNNING = 1;
   private int mPlayingState = STOPPED;
   private float toNumber;
   private float fromNumber
;
   private long duration = 1500;
   private int numberType = 2;
   private DecimalFormat fnum = new DecimalFormat("##0.00");
   private EndListener mEndListener = null;
   public RiseNumberTextView(Context context) {
this(context, null);
}

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);
}

public boolean isRunning() {
//返回當前執行狀態
return (mPlayingState == RUNNING);
}

private void runFloat() {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(fromNumber, toNumber);
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) {
//大於等於1時認為動畫執行結束
mPlayingState = STOPPED;
                           if (mEndListener != null)
mEndListener.onEndFinish();
}
}

});
valueAnimator.start();
}

private void runInt() {
ValueAnimator valueAnimator = ValueAnimator.ofInt((int) fromNumber,
(int) toNumber);
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();
}

@Override
public void start() {
if (!isRunning()) {
mPlayingState = RUNNING;
           if (numberType == 1)
runInt();
           else
runFloat();
}
}

@Override
public void setFloat(float fromNum, float toNum) {
toNumber = toNum;
numberType = 2;
fromNumber = fromNum;
}

@Override
public void setInteger(int fromNum, int toNum) {
toNumber = toNum;
numberType = 1;
fromNumber = fromNum;
}

@Override
public void setDuration(long duration) {
this.duration = duration;
}

@Override
public void setOnEndListener(EndListener callback) {
mEndListener = callback;
}

public interface EndListener {
void onEndFinish();
}
}

在佈局檔案中引用這個自定義個View,如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
   <ad.countviewdemo.RiseNumberTextView
android:id="@+id/risenumber_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
   <Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/risenumber_textview"
android:text="開始" />
</RelativeLayout>

最後在MainActivity.java中控制這個TextView,如下:

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() {
rnTextView = (RiseNumberTextView)
findViewById(R.id.risenumber_textview);
// 設定資料
rnTextView.setInteger(888, 1666);
// 設定動畫播放時間
rnTextView.setDuration(2000);
// 監聽動畫播放結束
rnTextView.setOnEndListener(new RiseNumberTextView.EndListener() {

@Override
public void onEndFinish() {
Toast.makeText(MainActivity.this, "資料增長完畢...",
Toast.LENGTH_SHORT).show();
}
});
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
if (rnTextView.isRunning()) {
Toast.makeText(MainActivity.this,
"數字還沒增長完,請稍候嘗試...",
Toast.LENGTH_SHORT).show();
} else {
// 開始播放動畫
rnTextView.start();
}
}
});
}
}

執行例項如下:

對於Float型別的,只需呼叫setFloat方法,如下: