歡迎您光臨本站 註冊首頁

android實現圓形漸變進度條

←手機掃碼閱讀     bom485332 @ 2020-06-01 , reply:0

最近項目中使用到了漸變效果的圓形進度條,網上找了很多漸變效果不夠圓滑,兩個漸變顏色之間有明顯的過渡,或者有些代碼畫出來的效果過渡不美觀,於是自己參照寫了一個,喜歡的朋友可以參考或者直接使用。

先上一張效果圖,視頻錄製不太好,不過不影響效果

下面開始介紹實現代碼,比較簡單,直接貼代碼吧

1、聲明自定義屬性

在項目的valuse文件夾下新建attrs.xml,在裡面定義自定義控件需要的屬性



2、自定義一個進度條RoundProgres繼承view類

 package com.blankj.progressring; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.SweepGradient; import android.graphics.Typeface; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.animation.LinearInterpolator; import org.jetbrains.annotations.Nullable; /** * 類描述:漸變的圓形進度條 * * @author:lusy * @date :2018/10/17 */ public class RoundProgress extends View { private static final String TAG = "roundProgress"; /** * 背景圓環畫筆 */ private Paint bgPaint; /** * 白色標記畫筆 */ private Paint iconPaint; /** * 進度畫筆 */ private Paint progressPaint; /** * 進度文本畫筆 */ private Paint textPaint; /** * 背景圓環的顏色 */ private int bgColor; /** * 線條進度的顏色 */ private int iconColor; private int[] progressColor; /** * 中間進度百分比的字符串的顏色 */ private int textColor; /** * 中間進度百分比的字符串的字體大小 */ private float textSize; /** * 圓環的寬度 */ private float roundWidth; /** * 最大進度 */ private int max; /** * 當前進度 */ private float progress; /** * 是否顯示中間的進度 */ private boolean textIsDisplayable; /** * 圓環半徑 */ private int mRadius; private int center; private float startAngle = -90; private float currentAngle; private float currentProgress; public RoundProgress(Context context) { this(context, null); } public RoundProgress(Context context, @Nullable AttributeSet attrs) { super(context, attrs); TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgress); //獲取自定義屬性和默認值 bgColor = mTypedArray.getColor(R.styleable.RoundProgress_bgColor, Color.parseColor("#2d2d2d")); icOnColor= mTypedArray.getColor(R.styleable.RoundProgress_lineColor, Color.parseColor("#ffffff")); textColor = mTypedArray.getColor(R.styleable.RoundProgress_textColor, Color.parseColor("#ffffff")); textSize = mTypedArray.getDimension(R.styleable.RoundProgress_textSize, 15); roundWidth = mTypedArray.getDimension(R.styleable.RoundProgress_roundWidth, 5); max = mTypedArray.getInteger(R.styleable.RoundProgress_maxProgress, 100); textIsDisplayable = mTypedArray.getBoolean(R.styleable.RoundProgress_textIsDisplayable, true); progressColor = new int[]{Color.parseColor("#747eff"), Color.parseColor("#0018ff"), Color.TRANSPARENT}; mTypedArray.recycle(); initPaint(); } public RoundProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //測量控件應占的寬高大小,此處非必需,只是為了確保佈局中設置的寬高不一致時仍顯示完整的圓 int measureWidth = MeasureSpec.getSize(widthMeasureSpec); int measureHeight = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(Math.min(measureWidth, measureHeight), Math.min(measureWidth, measureHeight)); } private void initPaint() { bgPaint = new Paint(); bgPaint.setStyle(Paint.Style.STROKE); bgPaint.setAntiAlias(true); bgPaint.setColor(bgColor); bgPaint.setStrokeWidth(roundWidth); icOnPaint= new Paint(); iconPaint.setStyle(Paint.Style.STROKE); iconPaint.setAntiAlias(true); iconPaint.setColor(iconColor); iconPaint.setStrokeWidth(roundWidth); progressPaint = new Paint(); progressPaint.setStyle(Paint.Style.STROKE); progressPaint.setAntiAlias(true); progressPaint.setStrokeWidth(roundWidth); textPaint = new Paint(); textPaint.setStyle(Paint.Style.STROKE); textPaint.setTypeface(Typeface.DEFAULT_BOLD); textPaint.setAntiAlias(true); textPaint.setColor(textColor); textPaint.setTextSize(textSize); textPaint.setStrokeWidth(0); } @Override protected void onDraw(Canvas canvas) { /** * 畫最外層的大圓環 */ //獲取圓心的x座標 center = Math.min(getWidth(), getHeight()) / 2; // 圓環的半徑 mRadius = (int) (center - roundWidth / 2); RectF oval = new RectF(center - mRadius, center - mRadius, center + mRadius, center + mRadius); //畫背景圓環 canvas.drawArc(oval, startAngle, 360, false, bgPaint); //畫進度圓環 drawProgress(canvas, oval); canvas.drawArc(oval, startAngle, currentAngle, false, progressPaint); //畫白色圓環 float start = startAngle + currentAngle - 1; canvas.drawArc(oval, start, 3, false, iconPaint); //百分比文字 int percent = (int) (((float) progress / (float) max) * 100); //測量字體寬度,我們需要根據字體的寬度設置在圓環中間 String text = String.valueOf(percent)+"%"; Rect textRect = new Rect(); textPaint.getTextBounds(text, 0, text.length(), textRect); if (textIsDisplayable && percent >= 0) { //畫出進度百分比文字 float x = (getWidth() - textRect.width()) / 2; float y = (getHeight() + textRect.height()) / 2; canvas.drawText(text, x, y, textPaint); } if (currentProgress<progress) { currentProgress++; postInvalidate(); } } /** * 畫進度圓環 * * @param canvas * @param oval */ private void drawProgress(Canvas canvas, RectF oval) { float section = progress / 100; currentAngle = section * 360; //把需要繪製的角度分成100等分 float unitAngle = (float) (currentAngle / 100.0); for (float i = 0, end = currentProgress * unitAngle; i <= end; i++) { SweepGradient shader = new SweepGradient(center, center, progressColor, new float[]{0.0f, section, 1.0f}); Matrix matrix = new Matrix(); matrix.setRotate(startAngle, center, center); shader.setLocalMatrix(matrix); progressPaint.setShader(shader); canvas.drawArc(oval, startAngle + i, 1, false, progressPaint); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //計算外圓半徑 寬,高最小值-填充邊距/2 center = (Math.min(w, h)) / 2; mRadius = (int) ((Math.min(w, h)) - roundWidth / 2); } public int getMax() { return max; } /** * 設置進度的最大值 * * @param max */ public void setMax(int max) { if (max <0) { Log.e(TAG, "max progress not allow <0"); return; } this.max = max; } /** * 獲取進度 * * @return */ public float getProgress() { return progress; } /** * 設置進度 * * @param progressValue * @param useAnima 是否需要動畫 */ public void setProgress(float progressValue, boolean useAnima) { float percent = progressValue * max / 100; if (percent 100) { percent = 100; } //使用動畫 if (useAnima) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, percent); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { progress = (float) animation.getAnimatedValue(); postInvalidate(); } }); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.setDuration(1500); valueAnimator.start(); } else { this.progress = percent; postInvalidate(); } } public int getTextColor() { return textColor; } public void setTextColor(int textColor) { this.textColor = textColor; } public float getTextSize() { return textSize; } public void setTextSize(float textSize) { this.textSize = textSize; } public float getRoundWidth() { return roundWidth; } public void setRoundWidth(float roundWidth) { this.roundWidth = roundWidth; } public int[] getProgressColor() { return progressColor; } public void setProgressColor(int[] progressColor) { this.progressColor = progressColor; postInvalidate(); } public int getBgColor() { return bgColor; } public void setBgColor(int bgColor) { this.bgColor = bgColor; } public int getIconColor() { return iconColor; } public void setIconColor(int iconColor) { this.icOnColor= iconColor; } public boolean isTextIsDisplayable() { return textIsDisplayable; } public void setTextIsDisplayable(boolean textIsDisplayable) { this.textIsDisplayable = textIsDisplayable; } public int getmRadius() { return mRadius; } public void setmRadius(int mRadius) { this.mRadius = mRadius; } public int getCenter() { return center; } public void setCenter(int center) { this.center = center; } public float getStartAngle() { return startAngle; } public void setStartAngle(float startAngle) { this.startAngle = startAngle; } }


3、使用自定義進度條view

activity佈局文件使用如下,為了方便測試效果,新增進度加、進度減,修改進度條顏色的按鈕



[bom485332 ] android實現圓形漸變進度條已經有284次圍觀

http://coctec.com/docs/android/show-post-236544.html