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" />

扫描二维码关注公众号,回复: 2757028 查看本文章


使用方法非常简单,只需要在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>

将源码拷贝到自己的工程就可以啦。



猜你喜欢

转载自blog.csdn.net/Fy993912_chris/article/details/77369643