1. 程式人生 > >Android 自定義View ProgressBarHorizontal:橫向進度條、支援圓角、漸變、圖片

Android 自定義View ProgressBarHorizontal:橫向進度條、支援圓角、漸變、圖片

背景:因系統的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>

將原始碼拷貝到自己的工程就可以啦。