安卓滾動數字的實現(從0開始增加到指定數字)
阿新 • • 發佈:2019-01-22
核心思想就是在自定義View中重寫Animation中的applyTransformation方法,在其中使用postInvalidate()方法重新整理介面,呼叫onDraw()來實現數字變化。
以下是程式碼與註釋:
import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; import android.view.animation.Animation; import android.view.animation.Transformation; /** * 使用內部的Animation驅動View的onDraw使數字滾動 * @author WeiTao * */ public class RuningNumView extends View{ //這裡的digit表示的是位數,就是個十百千,因為專案需要所以加上的 private int count, digit; private String text; private MyAnimation anim; private Paint textPaint; private int textSize; private RectF frameRectangle = new RectF(); public RuningNumView(Context context) { super(context); init(); } public RuningNumView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RuningNumView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public void init(){ text = "0"; anim = new MyAnimation(); final float scale = getContext().getResources().getDisplayMetrics().density; textSize = (int) (33 * scale + 0.5f); textPaint = new Paint(Paint.ANTI_ALIAS_FLAG|Paint.LINEAR_TEXT_FLAG); textPaint.setColor(0xFFFFFFFF); textPaint.setStyle(Style.FILL_AND_STROKE); textPaint.setTextSize(textSize); } @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas){ //處理下要顯示出來的數字,這裡是為了獲得個十百位中的一位 String textStr = (count % (int)Math.pow(10,digit))/(int)Math.pow(10,digit-1) + ""; Rect bounds = new Rect(); textPaint.getTextBounds(textStr, 0, textStr.length(), bounds); //畫出數字 canvas.drawText(textStr, frameRectangle.centerX() - (textPaint.measureText(textStr) / 2), frameRectangle.centerY() + bounds.height() / 2, textPaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); int min = Math.min(width, height); setMeasuredDimension(min, min); frameRectangle.set(0, 0, min, min); } /** * * @param text 最終數字 * @param digit 要顯示的數位(1/2/3) */ public RuningNumView setTextAndDigit(String text, int digit){ this.text = text; this.digit = digit; return this; } public RuningNumView setDuration(long durationMillis){ anim.setDuration(durationMillis); return this; } public void startAnimation(){ this.startAnimation(anim); } public class MyAnimation extends Animation{ @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); if(interpolatedTime < 1.0f){ //隨著動畫播放,interpolatedTime會由0變化到1,通過它,我們可以獲取變化中的數字(乘以下總數就行了) count = (int)(interpolatedTime * Float.parseFloat(text)); }else{ count = Integer.parseInt(text); } postInvalidate();//呼叫onDraw() } } }
變數設定:
RuningNumView tx_num1, tx_num2, tx_num3;
String score = "750";
以下依次是百位、十位、個位,兩秒的動畫,同時執行:
tx_num1.setDuration(2000).setTextAndDigit(score, 3); tx_num2.setDuration(2000).setTextAndDigit(score, 2); tx_num3.setDuration(2000).setTextAndDigit(score, 1); tx_num1.startAnimation(); tx_num2.startAnimation(); tx_num3.startAnimation();
這裡外部用的是LinearLayout佈局:
<com.taotaojin.view.RuningNumView android:id="@+id/tx_num1" android:layout_width="45dp" android:layout_height="55dp"/> <com.taotaojin.view.RuningNumView android:id="@+id/tx_num2" android:layout_width="45dp" android:layout_height="55dp" /> <com.taotaojin.view.RuningNumView android:id="@+id/tx_num3" android:layout_width="45dp" android:layout_height="55dp"/>
當然,也可以寫成一個View就顯示完整數字,我把它們拆分開完全是因為專案需要。