android帶動畫的圓形進度條
阿新 • • 發佈:2019-01-02
偶然發現一個很好的app,圓環進度條,帶加速動畫,看起來相當不錯。嘗試著克隆一下。
反編譯一看,哇塞,啥3.1415926都幹出來了,太高階玩不轉啊,算了,想想其它方式吧。
先看效果圖:
這個草稿存了小半年.....先發布了再說。實現了預想的效果,具體程式碼稍後奉上。
程式碼:
package com.zkbc.finance.widget; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import com.zkbc.finance.R; /** * 自定義進度 * * @author Rock Lee * @date 2016年4月18日 */ public class MyProgessLine extends View { //需要執行動畫的引數名 private static final String PROGRESS_PROPERTY = "progress"; private Paint paint;// 畫筆 RectF rectF; private int bmColor;// 底部橫線顏色 private float bmHight;// 底部橫線高度 private int color;// 進度條顏色 private float hight;// 進度條高度 protected float progress; public void setColor(int color) { this.color = color; } public MyProgessLine(Context context) { this(context, null); } public MyProgessLine(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyProgessLine(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs); paint = new Paint(); rectF = new RectF(); TypedArray mTypedArray = context.getTheme().obtainStyledAttributes( attrs, R.styleable.MyProgressLine, defStyleAttr, 0); bmColor = mTypedArray.getColor(R.styleable.MyProgressLine_myProgressLine_bmColor, Color.GRAY); bmHight = mTypedArray .getDimension(R.styleable.MyProgressLine_myProgressLine_bmHight, 2); color = mTypedArray.getColor(R.styleable.MyProgressLine_myProgressLine_color, Color.BLUE); hight = mTypedArray.getDimension(R.styleable.MyProgressLine_myProgressLine_hight, 2); } @Override protected void onDraw(Canvas canvas) { paint.setColor(bmColor); paint.setStrokeCap(Paint.Cap.SQUARE);// 圓角 // paint.setStyle(Paint.Style.FILL); // 設定實心 paint.setStrokeWidth(bmHight); // 設定筆畫的寬度 paint.setAntiAlias(true); // 消除鋸齒 rectF.set(0, 0, getWidth(), bmHight); //canvas.drawRoundRect(rectF, bmHight / 2, bmHight / 2, paint); canvas.drawRect(0, 0, getWidth(), bmHight, paint); paint.setColor(color); paint.setStrokeWidth(hight); // 設定筆畫的寬度 rectF.set(0, 0, progress, bmHight); //矩形 // canvas.drawRoundRect(rectF, hight / 2, hight / 2, paint); canvas.drawRect(0, 0, progress, bmHight, paint); } public float getProgress() { return progress; } public void setProgress(float progress) { this.progress = progress * getWidth() / 100; invalidate(); } /** * 賦值+執行動畫 * * @param progressText 進度 float */ public void dodo(float progressText) { AnimatorSet animation = new AnimatorSet(); ObjectAnimator progressAnimation = ObjectAnimator.ofFloat(this, PROGRESS_PROPERTY, 0f, progressText); progressAnimation.setDuration(1000);//動畫耗時 progressAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); animation.playTogether(progressAnimation); animation.start(); } }
圓形進度View:
package com.sefford.circularprogressdrawable.sample; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Typeface; import android.util.AttributeSet; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.Scroller; public class MyCircle extends View { /** * 畫筆物件的引用 */ private Paint[] paints; RectF oval; /** * 圓環的顏色 */ private int roundColor; /** * 圓環的寬度 */ private float roundWidth; /** * 圓環進度的顏色 */ private int roundProgressColor; /** * 移動 */ Scroller scroller; public MyCircle(Context context) { this(context, null); } public MyCircle(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyCircle(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs); paints = new Paint[4]; for (int i = 0; i < paints.length; i++) { paints[i] = new Paint(); } oval = new RectF(); TypedArray mTypedArray = context.getTheme().obtainStyledAttributes( attrs, R.styleable.myRound, defStyleAttr, 0); roundColor = mTypedArray.getColor(R.styleable.myRound_myRoundColor, Color.GRAY); roundWidth = mTypedArray.getDimension(R.styleable.myRound_myRoundWidth, 3); roundProgressColor = mTypedArray.getColor( R.styleable.myRound_myRoundProgressColor, Color.RED); mTypedArray.recycle(); // AccelerateInterpolator localAccelerateInterpolator = new AccelerateInterpolator(); // this.scroller = new Scroller(context, localAccelerateInterpolator); } @Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); float centre = getWidth() / 2; // 獲取圓心的x座標 float radius = (centre - roundWidth / 2); // 圓環的半徑 paints[0].setColor(roundColor); // 設定圓環的顏色 paints[0].setStyle(Paint.Style.STROKE); // 設定空心 paints[0].setStrokeWidth(roundWidth); // 設定圓環的寬度 paints[0].setAntiAlias(true); // 消除鋸齒 paints[0].setStrokeCap(Paint.Cap.ROUND);// 圓角 canvas.drawCircle(centre, centre, radius, paints[0]); // 畫出圓環 paints[0].setColor(roundProgressColor); // 用於定義的圓弧的形狀和大小的界限.指定圓弧的外輪廓矩形區域 // 橢圓的上下左右四個點(View 左上角為0) oval.set(centre - radius, centre - radius, centre + radius, centre + radius); //畫圓弧 canvas.drawArc(oval, -90, progress, false, paints[0]); /** * 畫進度百分比的text */ paints[0].setStrokeWidth(0); paints[0].setColor(roundColor); paints[0].setTextSize(14); paints[0].setTypeface(Typeface.DEFAULT_BOLD); // 設定字型 float textWidth = paints[0].measureText(progressText + "%"); canvas.drawText(progressText + "%", centre - textWidth / 2, centre + 14 / 2, paints[0]); // 畫出進度百分比 } public static final String PROGRESS_PROPERTY = "progress"; protected float progress; protected float progressText; public float getProgress() { return progress; } public void setProgress(float progress) { this.progress = progress * 360 / 100; invalidate();// UI thread // postInvalidate();//non-UI thread. } public void dodo(float progressText, float progress) { this.progressText = progressText; this.progress = progress; //也可使用3.0的AnimationSet實現 // AnimationSet set = new AnimationSet(true); // set.setRepeatCount(AnimationSet.INFINITE); // set.setInterpolator(new AccelerateDecelerateInterpolator()); // set.start(); // this.setAnimation(set); //4.0以上,在AnimationSet基礎上封裝的,遺憾的是沒有Repeat AnimatorSet animation = new AnimatorSet(); ObjectAnimator progressAnimation = ObjectAnimator.ofFloat(this,"progress", 0f, progress); progressAnimation.setDuration(700);// 動畫執行時間 /* * AccelerateInterpolator 加速,開始時慢中間加速 * DecelerateInterpolator 減速,開始時快然後減速 * AccelerateDecelerateInterolator 先加速後減速,開始結束時慢,中間加速 * AnticipateInterpolator 反向 ,先向相反方向改變一段再加速播放 * AnticipateOvershootInterpolator 反向加超越,先向相反方向改變,再加速播放,會超出目的值然後緩慢移動至目的值 * BounceInterpolator 跳躍,快到目的值時值會跳躍,如目的值100,後面的值可能依次為85,77,70,80,90,100 * CycleIinterpolator 迴圈,動畫迴圈一定次數,值的改變為一正弦函式:Math.sin(2 * * mCycles * Math.PI * input) LinearInterpolator 線性,線性均勻改變 * OvershottInterpolator 超越,最後超出目的值然後緩慢改變到目的值 * TimeInterpolator 一個介面,允許你自定義interpolator,以上幾個都是實現了這個介面 */ progressAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); animation.playTogether(progressAnimation);//動畫同時執行,可以做多個動畫 animation.start(); } }
還有屬性檔案attrs.xml:
<!-- 圓形進度條 --> <declare-styleable name="myRoundProgress"> <attr name="myRoundColor" format="color" /> <attr name="myRoundProgressColor" format="color" /> <attr name="myRoundWidth" format="dimension" /> <attr name="myRoundTextSize" format="dimension" /> </declare-styleable>