Android自定義分段式進度條
安卓自定義分段式的進度條,供大家參考,具體內(nèi)容如下
前一段時間公司新項目接到一個新需求,其中界面需要用到一個分段式的進度條,找了半天沒有發(fā)現(xiàn)類似的控件,于是決定自己寫一個,話不多說,上代碼
package com.djt.aienglish.widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Build; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import com.djt.aienglish.R; /** * 分段式進度條 * * @author qiu * @date 2021/3/2 14:34 */ public class SegmentProgressBar extends View { /** * 設(shè)置各種默認值 */ private static final int DEFAULT_HEIGHT_PROGRESS_BAR = 10; /** * 進度條圓角 */ private static final float mRadius = 60; /** * 背景色 */ private int defaultBackgroundColor = Color.parseColor("#DDE4F4"); /** * 進度條顏色 */ private int defaultProgressBarColor = Color.parseColor("#3D7EFE"); /** * 所有畫圖所用的畫筆 */ protected Paint mPaint = new Paint(); /** * 進度條間距 */ protected float mOffset = 0; protected float mDefaultOffset = 10; /** * 進度條高度 */ protected int mProgressBarHeight = dp2px(DEFAULT_HEIGHT_PROGRESS_BAR); /** * 除padding外的視圖寬度 */ protected float mRealWidth; /** * 最大值 */ private int mMax = 100; /** * 當前進度 */ private int mProgress = 0; /** * 分段寬度 */ private float progressWith = 0; public SegmentProgressBar(Context context) { this(context, null); } public SegmentProgressBar(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public SegmentProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initDefaultValues(context, attrs, defStyleAttr); init(); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public SegmentProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initDefaultValues(context, attrs, defStyleAttr); init(); } /** * 初始化布局 * * @param context * @param attrs * @param defStyleAttr */ private void initDefaultValues(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.ProgressBar, defStyleAttr, defStyleAttr); if (arr != null) { mProgress = arr.getInt(R.styleable.ProgressBar_progress, 0); mMax = arr.getInt(R.styleable.ProgressBar_max, 0); defaultBackgroundColor = arr.getColor(R.styleable.ProgressBar_progressBackground, Color.parseColor("#DDE4F4")); defaultProgressBarColor = arr.getColor(R.styleable.ProgressBar_progressBarColor, Color.parseColor("#3D7EFE")); } arr.recycle(); } /** * 初始化布局 */ private void init() { } /** * 最大值 * * @param max */ public void setMax(int max) { this.mMax = max; if (max > 0) { mOffset = mRealWidth / mMax / 8; if (mOffset > mDefaultOffset) { mOffset = mDefaultOffset; } progressWith = (mRealWidth - (mMax - 1) * mOffset) / mMax; } invalidate(); } /** * 進度值 * * @param progress */ public void setProgress(int progress) { this.mProgress = progress; invalidate(); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); //高度 int height = measureHeight(heightMeasureSpec); //必須調(diào)用該方法來存儲View經(jīng)過測量的到的寬度和高度 setMeasuredDimension(width, height); //真正的寬度值是減去左右padding mRealWidth = getMeasuredWidth() - getPaddingRight() - getPaddingLeft(); //使用畫筆在畫布上繪制進度 if (mMax > 0) { mOffset = mRealWidth / mMax / 8; if (mOffset > mDefaultOffset) { mOffset = mDefaultOffset; } progressWith = (mRealWidth - (mMax - 1) * mOffset) / mMax; } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //真正的寬度值是減去左右padding mRealWidth = w - getPaddingRight() - getPaddingLeft(); //使用畫筆在畫布上繪制進度 if (mMax > 0) { mOffset = mRealWidth / mMax / 8; if (mOffset > mDefaultOffset) { mOffset = mDefaultOffset; } progressWith = (mRealWidth - (mMax - 1) * mOffset) / mMax; } invalidate(); } /** * EXACTLY:父控件告訴我們子控件了一個確定的大小,你就按這個大小來布局。比如我們指定了確定的dp值和macth_parent的情況。 * AT_MOST:當前控件不能超過一個固定的最大值,一般是wrap_content的情況。 * UNSPECIFIED:當前控件沒有限制,要多大就有多大,這種情況很少出現(xiàn)。 * * @param measureSpec * @return 視圖的高度 */ private int measureHeight(int measureSpec) { int result = 0; //父布局告訴我們控件的類型 int specMode = MeasureSpec.getMode(measureSpec); //父布局傳過來的視圖大小 int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = (int) (getPaddingTop() + getPaddingBottom() + mProgressBarHeight); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(defaultBackgroundColor); //設(shè)置畫筆類型 mPaint.setStyle(Paint.Style.FILL); //去除鋸齒 mPaint.setAntiAlias(true); //使用畫筆在畫布上繪制背景 canvas.drawRoundRect(0, 0, mRealWidth, getHeight(), mRadius, mRadius, mPaint); //繪制進度條 mPaint.setColor(defaultProgressBarColor); for (int i = 0; i < mProgress; i++) { canvas.drawRoundRect(i * (progressWith + mOffset), 0, progressWith + i * (progressWith + mOffset), getHeight(), mRadius, mRadius, mPaint); } } /** * dp 2 px * * @param dpVal */ protected int dp2px(int dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics()); } }
別忘了在value下的attr.xml加上默認屬性配置
<!--分段式進度條--> <declare-styleable name="ProgressBar"> <attr name="progress" format="integer" /> <attr name="max" format="integer" /> <attr name="progressBarColor" format="color" /> <attr name="progressBackground" format="color" /> </declare-styleable>
在布局中使用
<com.djt.aienglish.widget.SegmentProgressBar android:id="@+id/spb" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" app:max="10" app:progress="1" />
最后再來一個實際使用效果。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android設(shè)計模式之適配器(Adapter)模式
這篇文章主要介紹了Android設(shè)計模式之適配器(Adapter)模式,以源碼解析的方式分析適配器模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11Android-Service實現(xiàn)手機壁紙自動更換
這篇文章主要為大家詳細介紹了Android-Service實現(xiàn)手機壁紙自動更換,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-11-11Android框架Volley使用之Json請求實現(xiàn)
這篇文章主要介紹了Android框架Volley使用之Json請求實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值 ,需要的朋友可以參考下2019-05-05Android實現(xiàn)網(wǎng)易新聞客戶端側(cè)滑菜單(2)
這篇文章主要為大家詳細介紹了Android實現(xiàn)網(wǎng)易新聞客戶端側(cè)滑菜單第二篇,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11Android動態(tài)模糊效果的快速實現(xiàn)方法
這篇文章主要介紹了Android動態(tài)模糊效果的快速實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01