Android自定義分段式進(jìn)度條
安卓自定義分段式的進(jìn)度條,供大家參考,具體內(nèi)容如下
前一段時(shí)間公司新項(xiàng)目接到一個(gè)新需求,其中界面需要用到一個(gè)分段式的進(jìn)度條,找了半天沒有發(fā)現(xiàn)類似的控件,于是決定自己寫一個(gè),話不多說,上代碼
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;
/**
* 分段式進(jìn)度條
*
* @author qiu
* @date 2021/3/2 14:34
*/
public class SegmentProgressBar extends View {
/**
* 設(shè)置各種默認(rèn)值
*/
private static final int DEFAULT_HEIGHT_PROGRESS_BAR = 10;
/**
* 進(jìn)度條圓角
*/
private static final float mRadius = 60;
/**
* 背景色
*/
private int defaultBackgroundColor = Color.parseColor("#DDE4F4");
/**
* 進(jìn)度條顏色
*/
private int defaultProgressBarColor = Color.parseColor("#3D7EFE");
/**
* 所有畫圖所用的畫筆
*/
protected Paint mPaint = new Paint();
/**
* 進(jìn)度條間距
*/
protected float mOffset = 0;
protected float mDefaultOffset = 10;
/**
* 進(jìn)度條高度
*/
protected int mProgressBarHeight = dp2px(DEFAULT_HEIGHT_PROGRESS_BAR);
/**
* 除padding外的視圖寬度
*/
protected float mRealWidth;
/**
* 最大值
*/
private int mMax = 100;
/**
* 當(dāng)前進(jìn)度
*/
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();
}
/**
* 進(jìn)度值
*
* @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)用該方法來存儲(chǔ)View經(jīng)過測量的到的寬度和高度
setMeasuredDimension(width, height);
//真正的寬度值是減去左右padding
mRealWidth = getMeasuredWidth() - getPaddingRight() - getPaddingLeft();
//使用畫筆在畫布上繪制進(jìn)度
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();
//使用畫筆在畫布上繪制進(jìn)度
if (mMax > 0) {
mOffset = mRealWidth / mMax / 8;
if (mOffset > mDefaultOffset) {
mOffset = mDefaultOffset;
}
progressWith = (mRealWidth - (mMax - 1) * mOffset) / mMax;
}
invalidate();
}
/**
* EXACTLY:父控件告訴我們子控件了一個(gè)確定的大小,你就按這個(gè)大小來布局。比如我們指定了確定的dp值和macth_parent的情況。
* AT_MOST:當(dāng)前控件不能超過一個(gè)固定的最大值,一般是wrap_content的情況。
* UNSPECIFIED:當(dāng)前控件沒有限制,要多大就有多大,這種情況很少出現(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);
//繪制進(jìn)度條
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加上默認(rèn)屬性配置
<!--分段式進(jìn)度條-->
<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" />
最后再來一個(gè)實(shí)際使用效果。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android自定義進(jìn)度條移動(dòng)效果
- Android實(shí)現(xiàn)簡單的加載進(jìn)度條
- Android實(shí)現(xiàn)帶有指示器的進(jìn)度條
- Android Studio實(shí)現(xiàn)進(jìn)度條效果
- Android ProgressBar 模擬進(jìn)度條效果的實(shí)現(xiàn)
- Android自定義圓環(huán)式進(jìn)度條
- Android自定義圓形進(jìn)度條效果
- Android自定義View實(shí)現(xiàn)圓形進(jìn)度條
- Android實(shí)現(xiàn)進(jìn)度條(ProgressBar)的功能與用法
- Android實(shí)現(xiàn)下載進(jìn)度條效果
相關(guān)文章
Android設(shè)計(jì)模式之適配器(Adapter)模式
這篇文章主要介紹了Android設(shè)計(jì)模式之適配器(Adapter)模式,以源碼解析的方式分析適配器模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
移動(dòng)端html5圖片上傳方法【更好的兼容安卓IOS和微信】
這篇文章主要為大家詳細(xì)介紹了移動(dòng)端html5圖片上傳方法,更好的兼容安卓IOS和微信,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06
Android-Service實(shí)現(xiàn)手機(jī)壁紙自動(dòng)更換
這篇文章主要為大家詳細(xì)介紹了Android-Service實(shí)現(xiàn)手機(jī)壁紙自動(dòng)更換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
Android框架Volley使用之Json請求實(shí)現(xiàn)
這篇文章主要介紹了Android框架Volley使用之Json請求實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-05-05
Android實(shí)現(xiàn)網(wǎng)易新聞客戶端側(cè)滑菜單(2)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)網(wǎng)易新聞客戶端側(cè)滑菜單第二篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
Android動(dòng)態(tài)模糊效果的快速實(shí)現(xiàn)方法
這篇文章主要介紹了Android動(dòng)態(tài)模糊效果的快速實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01

