您好,登錄后才能下訂單哦!
這篇文章主要講解了android實現圓形漸變進度條的方法,內容清晰明了,對此有興趣的小伙伴可以學習一下,相信大家閱讀完之后會有幫助。
最近項目中使用到了漸變效果的圓形進度條,網上找了很多漸變效果不夠圓滑,兩個漸變顏色之間有明顯的過渡,或者有些代碼畫出來的效果過渡不美觀,于是自己參照寫了一個,喜歡的朋友可以參考或者直接使用。
先上一張效果圖,視頻錄制不太好,不過不影響效果
下面開始介紹實現代碼,比較簡單,直接貼代碼吧
1、聲明自定義屬性
在項目的valuse文件夾下新建attrs.xml,在里面定義自定義控件需要的屬性
<declare-styleable name="RoundProgress"> <attr name="bgColor" format="color" /> <attr name="roundWidth" format="dimension" /> <attr name="textColor" format="color" /> <attr name="textSize" format="dimension" /> <attr name="maxProgress" format="integer" /> <attr name="textIsDisplayable" format="boolean" /> <attr name="lineColor" format="color" /> </declare-styleable>
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 < 0) { percent = 0; } 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布局文件使用如下,為了方便測試效果,新增進度加、進度減,修改進度條顏色的按鈕
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#242424" android:gravity="center"> <LinearLayout android:id="@+id/buttonLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" android:gravity="center_horizontal" android:orientation="horizontal"> <Button android:id="@+id/addProgress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="進度+" /> <Button android:id="@+id/changeColor" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:text="設置顏色" /> <Button android:id="@+id/subtraceProgress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="進度-" /> </LinearLayout> <com.blankj.progressring.RoundProgress android:id="@+id/socProgress" android:layout_width="70dp" android:layout_height="70dp" android:layout_below="@id/buttonLayout" android:layout_centerHorizontal="true" android:layout_gravity="center" android:layout_marginLeft="20dp" android:layout_marginBottom="2dp" app:bgColor="@color/bgColor" app:maxProgress="100" app:roundWidth="8dp" app:textIsDisplayable="true" app:textSize="18sp" /> </RelativeLayout>
看完上述內容,是不是對android實現圓形漸變進度條的方法有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。