因爲在項目中須要在一個view中顯示三個進度,因此自定義了一個三端指示進度條,下面簡單介紹一下它的使用,但願能對你們有所幫助,若是有不對之處,請多包涵,歡迎指正。android
1.在項目的根build.gradle下添加git
allprojects { repositories { ... maven { url 'https://jitpack.io' } } }
2.在本身的Module的build.gradle下添加依賴github
dependencies { implementation 'com.github.MingYueChunQiu:ThreeIndicatorProgressBar:1.0' }
1.在xml中進行使用canvas
<com.zhuolong.threeindicatorprogressbar.ui.ThreeIndicatorProgressBar android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:max="10" android:progress="2" app:barRoundedRadius="10dp" app:isHeadDrawable="true" app:isTailDrawable="true" app:progressBarHeight="30dp" app:progressTextSize="20sp" app:headBarColor="@android:color/holo_green_dark" app:middleBarColor="@android:color/darker_gray" app:tailBarColor="@android:color/holo_red_dark" app:tailProgress="3" />
2.在代碼中使用Builder模式建立對象app
ThreeIndicatorProgressBar progressBar = new ThreeIndicatorProgressBar.Builder(this) .setBarHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics())) .setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 30, getResources().getDisplayMetrics())) .setHeadBarColor(Color.GREEN) .setMiddleBarColor(Color.GRAY) .setTailBarColor(Color.RED) .setHeadCircleColor(Color.BLUE) .setTailCircleColor(Color.BLUE) .setMax(10) .setProgress(2) .setTailProgress(4) .build(); progressBar.setTailProgress(2); ((LinearLayoutCompat)findViewById(R.id.cl_container)) .addView(progressBar);
3.項目的源代碼:maven
public class ThreeIndicatorProgressBar extends ProgressBar { private static final int DEFAULT_BAR_ROUNDED_RADIUS = 25;//默認進度條圓角度數 private static final int DEFAULT_BAR_HEIGHT = 20;//默認進度條高度 private static final int DEFAULT_TEXT_SIZE = 20;//默認文字大小 private int mBarRoundedRadius;//進度條圓角矩形角度 private int mHeadBarColor, mMiddleBarColor, mTailBarColor, mHeadCircleColor, mTailCircleColor; private int mProgressTotalWidth; private int mTailProgress;//記錄尾端進度 private boolean isPercentage, isHeadDrawable, isTailDrawable;//標記是否顯示做業百分比,頭部和底部是否繪製圖片仍是圓圈 private Paint mPaint; private int mHeight;//總高度 private int mBarHeight;//進度條高度 private int mTextSize;//提示文字大小 private int mHeadBarDrawableId, mTailBarDrawableId;//頭部和尾部進度圖標資源ID private Bitmap mHeadBarBitmap, mTailBarBitmap;//頭部和尾部進度圖標 private float mRadius;//頭部進度指示頭半徑 private boolean isFromHead;//標記進度是從頭部仍是尾部變化 public ThreeIndicatorProgressBar(Builder builder) { this(builder.context); mBarRoundedRadius = builder.barRoundedRadius; mHeadBarColor = builder.headBarColor; mMiddleBarColor = builder.middleBarColor; mTailBarColor = builder.tailBarColor; mHeadCircleColor = builder.headCircleColor; mTailCircleColor = builder.tailCircleColor; mProgressTotalWidth = builder.progressTotalWidth; setMax(builder.max); setProgress(builder.progress); mTailProgress = builder.tailProgress; isPercentage = builder.isPercentage; isHeadDrawable = builder.isHeadDrawable; isTailDrawable = builder.isTailDrawable; mBarHeight = builder.barHeight; mTextSize = builder.textSize; mHeadBarDrawableId = builder.headBarDrawableId; mTailBarDrawableId = builder.tailBarDrawableId; initPadding(0.5f); } public ThreeIndicatorProgressBar(Context context) { this(context, null); } public ThreeIndicatorProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ThreeIndicatorProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttributes(context, attrs); initPadding(0.5f); } @Override public synchronized void setProgress(int progress) { super.setProgress(progress); isFromHead = true; } public int getTailProgress() { return mTailProgress; } public void setTailProgress(int tailProgress) { mTailProgress = tailProgress; isFromHead = false; invalidate(); } public boolean isPercentage() { return isPercentage; } public void setPercentage(boolean percentage) { isPercentage = percentage; } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); mHeight = measureHeight(heightMeasureSpec); mProgressTotalWidth = width - getPaddingLeft() - getPaddingRight(); setMeasuredDimension(width, mHeight); initDrawable(); } @Override protected synchronized void onDraw(Canvas canvas) { float headRadio = getProgress() * 1.0f / getMax(); float headProgressX = mProgressTotalWidth * headRadio; float tailRadio = getTailProgress() * 1.0f / getMax(); float tailProgressX = mProgressTotalWidth - mProgressTotalWidth * tailRadio; String headText, tailText, middleText; if (isPercentage) { headText = getProgress() + "%"; tailText = getTailProgress() + "%"; middleText = (getMax() - getProgress() - getTailProgress()) + "%"; } else { headText = getProgress() + ""; tailText = getTailProgress() + ""; middleText = (getMax() - getProgress() - getTailProgress()) + ""; } // float radius = (mBarHeight + getPaddingTop() + getPaddingBottom()) / 2; //繪製首端進度 Paint headPaint = new Paint(Paint.ANTI_ALIAS_FLAG); Path headPath = new Path(); headPaint.setColor(mHeadBarColor); RectF headRectF = new RectF(getPaddingLeft(), getPaddingTop(), headProgressX, mBarHeight + getPaddingTop()); float[] headRadius = new float[]{mBarRoundedRadius, mBarRoundedRadius, 0, 0, 0, 0, mBarRoundedRadius, mBarRoundedRadius}; headPath.addRoundRect(headRectF, headRadius, Path.Direction.CW); canvas.drawPath(headPath, headPaint); //繪製尾端進度 float tailX = tailProgressX; if (tailX < headProgressX) { tailX = headProgressX; } Paint tailPaint = new Paint(Paint.ANTI_ALIAS_FLAG); Path tailPath = new Path(); tailPaint.setColor(mTailBarColor); RectF tailRectF = new RectF(tailX + getPaddingLeft(), getPaddingTop(), mProgressTotalWidth + getPaddingLeft(), mBarHeight + getPaddingTop()); float[] tailRadius = new float[]{0, 0, mBarRoundedRadius, mBarRoundedRadius, mBarRoundedRadius, mBarRoundedRadius, 0, 0}; tailPath.addRoundRect(tailRectF, tailRadius, Path.Direction.CW); canvas.drawPath(tailPath, tailPaint); //繪製中間進度,若是有一頭爲0,則繪製圓角矩形,不然繪製矩形 Paint middlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); middlePaint.setColor(mMiddleBarColor); RectF middleRectF = new RectF(headProgressX + getPaddingLeft(), getPaddingTop(), tailProgressX + getPaddingLeft(), mBarHeight + getPaddingTop()); float[] middleRadius = null; if (getProgress() <= 0 || getTailProgress() <= 0) { middleRadius = new float[]{mBarRoundedRadius, mBarRoundedRadius, mBarRoundedRadius, mBarRoundedRadius, mBarRoundedRadius, mBarRoundedRadius, mBarRoundedRadius, mBarRoundedRadius}; } if (middleRadius == null) { canvas.drawRect(middleRectF, middlePaint); } else { Path middlePath = new Path(); middlePath.addRoundRect(middleRectF, middleRadius, Path.Direction.CW); canvas.drawPath(middlePath, middlePaint); } Paint circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); //先繪製尾端指示圓,這樣當兩端交匯時,會由首端的指示圓覆蓋掉尾端的指示圓 // drawIndicatorCircle(canvas, mTailBarColor, tailProgressX, mRadius, circlePaint); if (isFromHead) { if (isHeadDrawable && mHeadBarBitmap != null) { canvas.drawBitmap(mHeadBarBitmap, headProgressX - mRadius, 0, mPaint); } else { drawIndicatorCircle(canvas, mHeadCircleColor, headProgressX, mRadius, circlePaint); } } else { if (isTailDrawable && mTailBarBitmap != null) { canvas.drawBitmap(mTailBarBitmap, tailProgressX - mRadius, 0, mPaint); } else { drawIndicatorCircle(canvas, mTailCircleColor, tailProgressX, mRadius, circlePaint); } } drawIndicatorText(canvas, headProgressX, tailProgressX, headText, tailText, middleText); } public void setHeadIndicatorRadius(float radius) { mRadius = radius; } public float getHeadIndicatorRadius() { return mRadius; } private void initAttributes(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ThreeIndicatorProgressBar); if (a != null) { mBarRoundedRadius = a.getDimensionPixelSize(R.styleable.ThreeIndicatorProgressBar_barRoundedRadius, DEFAULT_BAR_ROUNDED_RADIUS); mHeadBarColor = a.getColor(R.styleable.ThreeIndicatorProgressBar_headBarColor, Color.GREEN); mMiddleBarColor = a.getColor(R.styleable.ThreeIndicatorProgressBar_middleBarColor, Color.WHITE); mTailBarColor = a.getColor(R.styleable.ThreeIndicatorProgressBar_tailBarColor, Color.RED); isPercentage = a.getBoolean(R.styleable.ThreeIndicatorProgressBar_isIndicatorPercentage, false); isHeadDrawable = a.getBoolean(R.styleable.ThreeIndicatorProgressBar_isHeadDrawable, false); isTailDrawable = a.getBoolean(R.styleable.ThreeIndicatorProgressBar_isTailDrawable, false); mTailProgress = a.getInteger(R.styleable.ThreeIndicatorProgressBar_tailProgress, 0); mBarHeight = a.getDimensionPixelSize(R.styleable.ThreeIndicatorProgressBar_progressBarHeight, DEFAULT_BAR_HEIGHT); mHeadCircleColor = a.getColor(R.styleable.ThreeIndicatorProgressBar_headCircleColor, Color.YELLOW); mTailCircleColor = a.getColor(R.styleable.ThreeIndicatorProgressBar_tailCircleColor, Color.BLUE); mTextSize = a.getDimensionPixelSize(R.styleable.ThreeIndicatorProgressBar_progressTextSize, DEFAULT_TEXT_SIZE); mHeadBarDrawableId = a.getResourceId(R.styleable.ThreeIndicatorProgressBar_headBarDrawable, R.drawable.sun); mTailBarDrawableId = a.getResourceId(R.styleable.ThreeIndicatorProgressBar_tailBarDrawable, R.drawable.moon); a.recycle(); } } private void initPadding(float ratio) { int padding = (int) (mBarHeight * ratio); setPadding(0, padding, 0, padding); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setTextSize(mTextSize); mPaint.setColor(Color.WHITE); mRadius = (mBarHeight + getPaddingTop() + getPaddingBottom()) / 2; } private void initDrawable() { Bitmap headBitmap = BitmapFactory.decodeResource(getResources(), mHeadBarDrawableId); Bitmap tailBitmap = BitmapFactory.decodeResource(getResources(), mTailBarDrawableId); // mHeadBarBitmap = Bitmap.createScaledBitmap(headBitmap, (int)mRadius * 2, (int)mRadius * 2, false); // mTailBarBitmap = Bitmap.createScaledBitmap(tailBitmap, (int)mRadius * 2, (int)mRadius * 2, false); //這種縮放圖片方法,將大圖片縮放成小圖片時,效果比上面的好,但仍是會失真 if (headBitmap != null) { Matrix headMatrix = new Matrix(); headMatrix.postScale(mRadius * 2 / headBitmap.getWidth(), mRadius * 2 / headBitmap.getHeight()); mHeadBarBitmap = Bitmap.createBitmap(headBitmap, 0, 0, headBitmap.getWidth(), headBitmap.getHeight(), headMatrix, true); } if (tailBitmap != null) { Matrix tailMatrix = new Matrix(); tailMatrix.postScale(mRadius * 2 / tailBitmap.getWidth(), mRadius * 2 / tailBitmap.getHeight()); mTailBarBitmap = Bitmap.createBitmap(tailBitmap, 0, 0, tailBitmap.getWidth(), tailBitmap.getHeight(), tailMatrix, true); } } /** * 繪製首尾兩端指示文本 * * @param canvas 畫布 * @param headProgressX 頭部文字位置 * @param tailProgressX 尾部文字位置 * @param headText 頭部文字 * @param tailText 尾部文字 * @param middleText 中間文字 */ private void drawIndicatorText(Canvas canvas, float headProgressX, float tailProgressX, String headText, String tailText, String middleText) { Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); textPaint.setTextSize(mTextSize); textPaint.setColor(Color.WHITE); Paint.FontMetrics fontMetrics = textPaint.getFontMetrics(); float headTextWidth = textPaint.measureText(headText); float tailTextWidth = textPaint.measureText(tailText); float middleTextWidth = textPaint.measureText(middleText); float baseline = getPaddingTop() + mBarHeight / 2 + (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom; if ((isHeadDrawable && headProgressX >= headTextWidth && mHeadBarBitmap != null) || (!isHeadDrawable && !isFromHead)) { canvas.drawText(headText, getPaddingLeft() + (headProgressX - headTextWidth) / 2, baseline, textPaint); } else { canvas.drawText(headText, getPaddingLeft() + headProgressX - textPaint.measureText(headText) / 2, baseline, textPaint); } if ((isTailDrawable && mProgressTotalWidth - tailProgressX >= tailTextWidth && mTailBarBitmap != null) || (!isTailDrawable && isFromHead)) { canvas.drawText(tailText, getPaddingLeft() + tailProgressX + (mProgressTotalWidth - tailProgressX - tailTextWidth) / 2, baseline, textPaint); } else { canvas.drawText(tailText, getPaddingLeft() + tailProgressX - textPaint.measureText(tailText) / 2, baseline, textPaint); } //在進度條中間繪製指示進度文本 if (tailProgressX - headProgressX >= middleTextWidth) { canvas.drawText(middleText, headProgressX + (tailProgressX - headProgressX) / 2, baseline, textPaint); } } /** * 繪製指示圓圈 * * @param canvas 圓圈畫布 * @param color 圓圈實心顏色 * @param progressX 左端x座標 * @param radius 圓圈半徑 * @param circlePaint 圓圈畫筆 */ private void drawIndicatorCircle(Canvas canvas, int color, float progressX, float radius, Paint circlePaint) { circlePaint.setStyle(Paint.Style.FILL); circlePaint.setColor(color); canvas.drawCircle(progressX, radius, radius, circlePaint); circlePaint.setStyle(Paint.Style.STROKE); circlePaint.setColor(Color.WHITE); canvas.drawCircle(progressX, radius, radius, circlePaint); } /** * 計算進度條高度 * * @param measureSpec 測量信息 * @return 返回肯定好的進度條高度 */ private int measureHeight(int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); float textHeight = mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top; if (mBarHeight < textHeight) { mBarHeight = (int) (textHeight); mRadius = (mBarHeight + getPaddingTop() + getPaddingBottom()) / 2; } int result = getPaddingTop() + getPaddingBottom() + mBarHeight; if (specMode == MeasureSpec.EXACTLY) { if (specSize > result) { result = specSize; } } else { if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } public static class Builder { private Context context; private int barRoundedRadius; private int headBarColor, middleBarColor, tailBarColor, headCircleColor, tailCircleColor; private int progressTotalWidth; private int max, progress, tailProgress;//記錄尾端進度 private boolean isPercentage, isHeadDrawable, isTailDrawable;//標記是否顯示做業百分比,頭部和底部是否繪製圖片仍是圓圈 private int barHeight;//進度條高度 private int textSize;//提示文字大小 private int headBarDrawableId, tailBarDrawableId;//頭部和尾部進度圖標資源ID public Builder(Context context) { this.context = context; } public ThreeIndicatorProgressBar build() { return new ThreeIndicatorProgressBar(this); } public void setBarRoundedRadius(int barRoundedRadius) { this.barRoundedRadius = barRoundedRadius; } public Builder setHeadBarColor(int headBarColor) { this.headBarColor = headBarColor; return this; } public Builder setMiddleBarColor(int middleBarColor) { this.middleBarColor = middleBarColor; return this; } public Builder setTailBarColor(int tailBarColor) { this.tailBarColor = tailBarColor; return this; } public Builder setHeadCircleColor(int headCircleColor) { this.headCircleColor = headCircleColor; return this; } public Builder setTailCircleColor(int tailCircleColor) { this.tailCircleColor = tailCircleColor; return this; } public Builder setProgressTotalWidth(int progressTotalWidth) { this.progressTotalWidth = progressTotalWidth; return this; } public Builder setMax(int max) { this.max = max; return this; } public Builder setProgress(int progress) { this.progress = progress; return this; } public Builder setTailProgress(int tailProgress) { this.tailProgress = tailProgress; return this; } public Builder setPercentage(boolean percentage) { isPercentage = percentage; return this; } public Builder setHeadDrawable(boolean headDrawable) { isHeadDrawable = headDrawable; return this; } public Builder setTailDrawable(boolean tailDrawable) { isTailDrawable = tailDrawable; return this; } public Builder setBarHeight(int barHeight) { this.barHeight = barHeight; return this; } public Builder setTextSize(int textSize) { this.textSize = textSize; return this; } public Builder setHeadBarDrawableId(int headBarDrawableId) { this.headBarDrawableId = headBarDrawableId; return this; } public Builder setTailBarDrawableId(int tailBarDrawableId) { this.tailBarDrawableId = tailBarDrawableId; return this; } } }
以上就是具體的使用方式,若是有什麼建議或者更好的方式,歡迎指出,下面是項目的GitHub地址:https://github.com/MingYueChunQiu/ThreeIndicatorProgressBar.git 碼雲地址:https://gitee.com/MingYueChunQiu/ThreeIndicatorProgressBar.gitide