Android 自定義View ProgressBarHorizontal:橫向進度條、支援圓角、漸變、圖片
阿新 • • 發佈:2018-12-31
背景:因系統的ProgressBar設定圖片時,如果圖片不夠大,而在大解析度的手機上時會出現無法填充滿,所以自己寫一個,既修復該問題,又可方便拓展,所以拋磚引玉
功能介紹:橫向進度條,分為背景與封面兩層,封面與背景均支援圓角矩形、漸變、圖片。
效果圖:
(上面仿微博載入圖片進度條在另一篇博文中:http://blog.csdn.net/fy993912_chris/article/details/77370206)
<com.example.work.myapplication.widget.ProgressBarHorizontal android:layout_width="match_parent"android:layout_height="25dp" app:pbhBgColorEnd="#01978a" app:pbhBgColorStart="#00a2e9" app:pbhBgRadius="15dp" app:pbhBgSrc="@mipmap/ic_health_bg_2" app:pbhCoverColorEnd="@color/colorAccent" app:pbhCoverColorStart="@color/colorPrimary" app:pbhCoverSrc="@mipmap/ic_life_bg" app:pbhProgress="50" app:pbhScaleType="match_parent" /> <com.example.work.myapplication.widget.ProgressBarHorizontal android:layout_width="match_parent" android:layout_height="25dp" android:layout_marginTop="5dp" app:pbhBgColorEnd="#01978a" app:pbhBgColorStart="#00a2e9" app:pbhBgRadius="15dp" app:pbhCoverColorEnd="@color/colorAccent" app:pbhCoverColorStart="@color/colorPrimary" app:pbhCoverSrc="@mipmap/ic_life_bg" app:pbhProgress="50" app:pbhScaleType="match_parent" /> <com.example.work.myapplication.widget.ProgressBarHorizontal android:layout_width="match_parent" android:layout_height="25dp" android:layout_marginTop="5dp" app:pbhBgColorEnd="#01978a" app:pbhBgColorStart="#00a2e9" app:pbhBgLbRadius="14dp" app:pbhBgLtRadius="14dp" app:pbhBgRbRadius="0dp" app:pbhBgRtRadius="0dp" app:pbhCoverColorEnd="@color/colorAccent" app:pbhCoverColorStart="@color/colorPrimary" app:pbhCoverLbRadius="14dp" app:pbhCoverLtRadius="14dp" app:pbhCoverRbRadius="0dp" app:pbhCoverRtRadius="0dp" app:pbhProgress="50" app:pbhScaleType="match_parent" />
使用方法非常簡單,只需要在xml中配置對應屬性便可實時預覽效果
需要注意的是控制元件會有一個優先級別顯示:
依次為:
圖片->圓角矩形
設定圓角時,radius會優於rt、rb、lt、lb屬性
scaleType:
match_content:以控制元件大小為準
wrap_content:以封面圖片大小為準
具體可以檢視程式碼或者配置xml進行檢視,這裡就不多說啦。
以下是程式碼--------------------------------------------------------------------------------------------------
clss類檔案原始碼
/** * Created by work on 2017/8/8. * 橫向進度條 * * @author chris zou * @mail [email protected] */ public class ProgressBarHorizontal extends View { public float maxProgress = 100; /*背景*/ Bitmap bgBitmap; int bgColorStart; int bgColorEnd; int[] bgColors; int bgRadius; int bgLtRadius; int bgLbRadius; int bgRbRadius; int bgRtRadius; Paint bgPaint; /*end*/ /*圖片*/ Bitmap coverBitmap; int coverColorStart; int coverColorEnd; int[] coverColors; int coverRadius; int coverLtRadius; int coverLbRadius; int coverRtRadius; int coverRbRadius; Paint coverPaint; /*end*/ int w, h; int compareMinSize;//高與寬較小那個 int scaleType; float progress; public ProgressBarHorizontal(Context context) { this(context, null); } public ProgressBarHorizontal(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public ProgressBarHorizontal(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context.obtainStyledAttributes(attrs, R.styleable.ProgressBarHorizontal)); } public void init(TypedArray typedArray) { setupParams(typedArray); setupPaint(); } /** * 設定引數 */ public void setupParams(TypedArray typedArray) { bgColorStart = typedArray.getColor(R.styleable.ProgressBarHorizontal_pbhBgColorStart, Color.DKGRAY); bgColorEnd = typedArray.getColor(R.styleable.ProgressBarHorizontal_pbhBgColorEnd, bgColorStart); bgColors = new int[]{bgColorStart, bgColorEnd}; bgRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgRadius, 0); bgLtRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgLtRadius, 0); bgLbRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgLbRadius, 0); bgRbRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgRbRadius, 0); bgRtRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhBgRtRadius, 0); Drawable coverDrawable = typedArray.getDrawable(R.styleable.ProgressBarHorizontal_pbhBgSrc); bgBitmap = coverDrawable != null ? ((BitmapDrawable) coverDrawable).getBitmap() : null; coverColorStart = typedArray.getColor(R.styleable.ProgressBarHorizontal_pbhCoverColorStart, Color.GRAY); coverColorEnd = typedArray.getColor(R.styleable.ProgressBarHorizontal_pbhCoverColorEnd, coverColorStart); coverColors = new int[]{coverColorStart, coverColorEnd}; coverRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverRadius, 0); coverLtRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverLtRadius, 0); coverLbRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverLbRadius, 0); coverRbRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverRbRadius, 0); coverRtRadius = typedArray.getDimensionPixelSize(R.styleable.ProgressBarHorizontal_pbhCoverRtRadius, 0); Drawable bottomDrawable = typedArray.getDrawable(R.styleable.ProgressBarHorizontal_pbhCoverSrc); coverBitmap = bottomDrawable != null ? ((BitmapDrawable) bottomDrawable).getBitmap() : null; progress = typedArray.getInteger(R.styleable.ProgressBarHorizontal_pbhProgress, 0); scaleType = typedArray.getInteger(R.styleable.ProgressBarHorizontal_pbhScaleType, 0); } public void setupPaint() { bgPaint = new Paint(); bgPaint.setColor(bgColorStart); bgPaint.setStyle(Paint.Style.FILL); bgPaint.setAntiAlias(true); coverPaint = new Paint(); coverPaint.setColor(coverColorStart); coverPaint.setStyle(Paint.Style.FILL); coverPaint.setAntiAlias(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (scaleType == 0) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } else { if (coverBitmap == null) { throw new NullPointerException("wrap_content must set image res"); } setMeasuredDimension(coverBitmap.getWidth(), coverBitmap.getHeight()); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.w = w; this.h = h; compareMinSize = w > h ? h : w; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //bg bgPaint.setShader(new LinearGradient(0, h / 2, w, h / 2, bgColors, null, Shader.TileMode.MIRROR)); if (bgBitmap != null) { canvas.drawBitmap(bgBitmap, null, new RectF(0, 0, w, h), null); } else if (bgRadius != 0) { RectF bgRec = new RectF(0, 0, w, h); canvas.drawRoundRect(bgRec, bgRadius, bgRadius, bgPaint); } else { drawPath(canvas, bgLtRadius, bgLbRadius, bgRbRadius, bgRtRadius, w, bgPaint); } //cover coverPaint.setShader(new LinearGradient(0, h / 2, w, h / 2, coverColors, null, Shader.TileMode.MIRROR)); float progressWidth = w - w * ((maxProgress - progress) / maxProgress); if (coverBitmap != null) { RectF imgRect = new RectF(0, 0, progressWidth, h); Rect srcRect = new Rect(0, 0, (int) progressWidth, h); canvas.drawBitmap(coverBitmap, srcRect, imgRect, null); } else if (coverRadius != 0) { RectF coverRec = new RectF(0, 0, progressWidth, h); canvas.drawRoundRect(coverRec, coverRadius, coverRadius, coverPaint); } else { drawPath(canvas, coverLtRadius, coverLbRadius, coverRbRadius, coverRtRadius, progressWidth, coverPaint); } } /** * 做一階貝塞爾曲線 * * @param canvas * @param lt * @param lb * @param rb * @param rt * @param w * @param paint */ private void drawPath(Canvas canvas, int lt, int lb, int rb, int rt, float w, Paint paint) { //左上角,逆時針開始 Path path = new Path(); //左上 path.moveTo(lt, 0); path.quadTo(0, 0, 0, lt); //左下 path.lineTo(0, h - lb); path.quadTo(0, h, lb, h); //右下 path.lineTo(w - rb, h); path.quadTo(w, h, w, h - rb); //右上 path.lineTo(w, rt); path.quadTo(w, 0, w - rt, 0); //回到左上角 path.lineTo(lt, 0); canvas.drawPath(path, paint); } /** * @param progress 0-100 */ public void setProgress(float progress) { if (progress > maxProgress) { progress = maxProgress; } this.progress = progress; postInvalidate(); } public void setBgColors(int[] colors) { this.bgColors = colors; } public void setCoverColors(int[] colors) { this.coverColors = colors; } }
attrs屬性內容
<declare-styleable name="ProgressBarHorizontal"> <attr name="pbhBgSrc" format="reference" /> <attr name="pbhBgColorStart" format="color" /> <attr name="pbhBgColorEnd" format="color" /> <attr name="pbhBgRadius" format="dimension" /> <attr name="pbhBgLtRadius" format="dimension" /> <attr name="pbhBgLbRadius" format="dimension" /> <attr name="pbhBgRbRadius" format="dimension" /> <attr name="pbhBgRtRadius" format="dimension" /> <attr name="pbhCoverSrc" format="reference" /> <attr name="pbhCoverColorStart" format="color" /> <attr name="pbhCoverColorEnd" format="color" /> <attr name="pbhCoverRadius" format="dimension" /> <attr name="pbhCoverLtRadius" format="dimension" /> <attr name="pbhCoverLbRadius" format="dimension" /> <attr name="pbhCoverRbRadius" format="dimension" /> <attr name="pbhCoverRtRadius" format="dimension" /> <attr name="pbhProgress" format="integer" /> <attr name="pbhScaleType"> <enum name="match_parent" value="0" /> <enum name="wrap_content" value="1" /> </attr> </declare-styleable>
將原始碼拷貝到自己的工程就可以啦。