自定义圆形进度条

来源:互联网 发布:上海卓易科技 大数据 编辑:程序博客网 时间:2024/06/15 05:56

背景

开发过程当中,当我们进行上传、下载或者更新等项目需求时,往往需要给用户展示一个进度值用于显示当前的更新状态,便于用户进行操作处理。当原生的控件满足不了展示需要时,就要我们自己定制所需要的展示效果,值此情景时各种各样的自定义进度展示控件便应用而生。以下简单介绍几种常见的显示样式,实现的方式大同小异,大家可以根据自己的需求简单修改配置即可。

效果图:
进度条

常见的使用样式

ProgressWheel使用

1.在attr.xml中定义属性

<declare-styleable name="ProgressWheel">    <!-- 文本内容 -->    <attr name="pwText" format="string" />    <!-- 文本字体颜色 -->    <attr name="pwTextColor" format="color" />    <!-- 文本字体大小 -->    <attr name="pwTextSize" format="dimension" />    <!-- 进度条颜色 -->    <attr name="pwBarColor" format="color" />    <!-- 进度条宽度 -->    <attr name="pwBarWidth" format="integer" />    <!-- 进度条默认长度 -->    <attr name="pwDefaultProgress" format="integer" />    <!-- 默认轮廓颜色 -->    <attr name="pwRimColor" format="color" />    <!-- 默认轮廓宽度 -->    <attr name="pwRimWidth" format="integer" />    <!-- 圆圈内部的颜色 -->    <attr name="pwCircleInnerColor" format="color" />    <!-- 控制外边缘颜色 -->    <attr name="pwOuterEdgeColor" format="color" />    <!-- 控制外边缘大小 -->    <attr name="pwOuterEdgeSize" format="dimension" />    <!-- 控制内边缘颜色 -->    <attr name="pwInnerEdgeColor" format="color" />    <!-- 控制内边缘大小 -->    <attr name="pwInnerEdgeSize" format="dimension" /></declare-styleable>

2.布局文件

<com.wiggins.progresswheel.widget.ProgressWheel    android:id="@+id/mProgressWheel"    android:layout_width="150dp"    android:layout_height="150dp"    android:layout_marginTop="@dimen/margin_normal"    app:pwBarColor="@color/red"    app:pwBarWidth="15"    app:pwDefaultProgress="49"    app:pwRimColor="@color/orange"    app:pwRimWidth="15" />

3.java文件调用

mProgressWheel.setProgress(pg);

4.绘制元素边界

private void setupBounds() {    // 为了保持宽度和长度的一致,我们要获得layout_width和layout_height中较小的一个,从而绘制一个圆    int minValue = Math.min(layoutWidth, layoutHeight);    // 计算在绘制过程中在x,y方向的偏移量    int xOffset = layoutWidth - minValue;    int yOffset = layoutHeight - minValue;    // 间距加上偏移量    paddingTop = this.getPaddingTop() + (yOffset / 2);    paddingBottom = this.getPaddingBottom() + (yOffset / 2);    paddingLeft = this.getPaddingLeft() + (xOffset / 2);    paddingRight = this.getPaddingRight() + (xOffset / 2);    int width = getWidth();    int height = getHeight();    innerEdgeBounds = new RectF(            paddingLeft + (1.5f * barWidth),            paddingTop + (1.5f * barWidth),            width - paddingRight - (1.5f * barWidth),            height - paddingBottom - (1.5f * barWidth));    outerEdgeBounds = new RectF(            paddingLeft + barWidth,            paddingTop + barWidth,            width - paddingRight - barWidth,            height - paddingBottom - barWidth);    innerEdgeContour = new RectF(            outerEdgeBounds.left + (rimWidth / 2.0f) + (outerEdgeSize / 2.0f),            outerEdgeBounds.top + (rimWidth / 2.0f) + (outerEdgeSize / 2.0f),            outerEdgeBounds.right - (rimWidth / 2.0f) - (outerEdgeSize / 2.0f),            outerEdgeBounds.bottom - (rimWidth / 2.0f) - (outerEdgeSize / 2.0f));    outerEdgeContour = new RectF(            outerEdgeBounds.left - (rimWidth / 2.0f) - (innerEdgeSize / 2.0f),            outerEdgeBounds.top - (rimWidth / 2.0f) - (innerEdgeSize / 2.0f),            outerEdgeBounds.right + (rimWidth / 2.0f) + (innerEdgeSize / 2.0f),            outerEdgeBounds.bottom + (rimWidth / 2.0f) + (innerEdgeSize / 2.0f));}

5.绘制元素属性

private void setupPaints() {   //进度条    barPaint.setColor(barColor);//设置画笔颜色    barPaint.setAntiAlias(true);//设置抗锯齿    barPaint.setStyle(Style.STROKE);//设置画笔为空心    barPaint.setStrokeWidth(barWidth);//设置线宽    //圆环    rimPaint.setColor(rimColor);    rimPaint.setAntiAlias(true);    rimPaint.setStyle(Style.STROKE);    rimPaint.setStrokeWidth(rimWidth);    //环内    circleInnerPaint.setColor(circleInnerColor);    circleInnerPaint.setAntiAlias(true);    circleInnerPaint.setStyle(Style.FILL);    //字体    textPaint.setColor(textColor);    textPaint.setStyle(Style.FILL);    textPaint.setAntiAlias(true);    textPaint.setTextSize(textSize);    //外边缘    outerEdgePaint.setColor(outerEdgeColor);    outerEdgePaint.setAntiAlias(true);    outerEdgePaint.setStyle(Style.STROKE);    outerEdgePaint.setStrokeWidth(outerEdgeSize);    //内边缘    innerEdgePaint.setColor(innerEdgeColor);    innerEdgePaint.setAntiAlias(true);    innerEdgePaint.setStyle(Style.STROKE);    innerEdgePaint.setStrokeWidth(innerEdgeSize);}

6.绘制视图

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //绘制边界    canvas.drawArc(innerEdgeBounds, 360, 360, false, circleInnerPaint);    canvas.drawArc(outerEdgeBounds, 360, 360, false, rimPaint);    //绘制边缘    canvas.drawArc(outerEdgeContour, 360, 360, false, outerEdgePaint);    canvas.drawArc(innerEdgeContour, 360, 360, false, innerEdgePaint);    //绘制进度    canvas.drawArc(outerEdgeBounds, -90, progress, false, barPaint);    //绘制文字(并让它显示在圆水平和垂直方向的中心处)    float textHeight = textPaint.descent() - textPaint.ascent();    float verticalTextOffset = (textHeight / 2) - textPaint.descent();    for (String line : splitText) {        float horizontalTextOffset = textPaint.measureText(line) / 2;        canvas.drawText(                line,                this.getWidth() / 2 - horizontalTextOffset,                this.getHeight() / 2 + verticalTextOffset,                textPaint);    }}

RoundProgressBar使用

1.在attr.xml中定义属性

<declare-styleable name="RoundProgressBar">    <!-- 圆环颜色 -->    <attr name="roundColor" format="color" />    <!-- 圆环宽度 -->    <attr name="roundWidth" format="float" />    <!-- 进度条颜色 -->    <attr name="progressColor" format="color" />    <!-- 默认进度百分比 -->    <attr name="progressRatio" format="float" />    <!-- 字体颜色 -->    <attr name="textColors" format="color" />    <!-- 字体大小 -->    <attr name="textSizes" format="dimension" />    <!-- 是否显示进度百分比 -->    <attr name="textIsShow" format="boolean" /></declare-styleable>

2.布局文件

<com.wiggins.progresswheel.widget.RoundProgressBar    android:id="@+id/mRoundProgressBar"    android:layout_width="150dp"    android:layout_height="150dp"    app:progressColor="@color/blue"    app:roundColor="@color/red" />

3.java文件调用

mRoundProgressBar.setProgress(new float[]{getProgress(56), getProgress(90),                getProgress(120), getProgress(88), getProgress(80)},        new String[]{"#A0DD2A", "#FFAF8B", "#36D9F1", "#FFD71C", "#A89AFF"});

4.绘制元素边界

private void setupBounds() {    int minValue = Math.min(getWidth(), getHeight());    int centre = minValue / 2; // 获取圆心的x坐标    int radius = (int) (centre - mRoundWidth / 2); // 圆环的半径    mBounds = new RectF(centre - radius, centre - radius, centre + radius, centre + radius);}

5.绘制元素属性

private void setupPaints() {    mRoundPaint.setColor(mRoundColor);// 设置画笔颜色    mRoundPaint.setAntiAlias(true); // 消除锯齿    mRoundPaint.setStyle(Style.STROKE); // 设置空心    mRoundPaint.setStrokeWidth(mRoundWidth);// 设置线宽    mTextPaint.setColor(mTextColor);    mTextPaint.setTextSize(mTextSize);    mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);    mTextPaint.setStyle(Paint.Style.FILL);    mTextPaint.setAntiAlias(true);    mProgressPaint.setStrokeWidth(mRoundWidth);    mProgressPaint.setAntiAlias(true);    mProgressPaint.setStyle(Style.STROKE);}

6.绘制视图

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    // 绘制边界    canvas.drawArc(mBounds, 0, 360, false, mRoundPaint);    // 绘制进度百分比    int percent = Math.round((mProgressRatio / 360) * 100);    // 测量字体宽度    float textWidth = mTextPaint.measureText(percent + "%");    // 绘制的起点X轴坐标:画布宽度的一半 - 文字宽度的一半    int baseX = (int) (canvas.getWidth() / 2 - textWidth / 2);    // 绘制的起点Y轴坐标:画布高度的一半 - 文字总高度的一半    int baseY = (int) ((canvas.getHeight() / 2) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2));    // 绘制进度    float start = -90;    if (mRatio != null) {        for (int i = 0; i < mRatio.length; i++) {            mProgressPaint.setColor(Color.parseColor(mColors[i]));// 进度的颜色            canvas.drawArc(mBounds, start, mRatio[i], false, mProgressPaint);            start += mRatio[i];        }    } else {        mProgressPaint.setColor(mProgressColor); // 进度的颜色        canvas.drawArc(mBounds, start, mProgressRatio, false, mProgressPaint);        if (mTextIsShow) {            canvas.drawText(percent + "%", baseX, baseY, mTextPaint);        }    }}

RingProgressBar使用

1.在attr.xml中定义属性

<declare-styleable name="RingProgressBar">    <!-- 圆环颜色 -->    <attr name="ringColor" format="color" />    <!-- 圆环宽度 -->    <attr name="ringWidth" format="dimension" />    <!-- 圆环是否空心 -->    <attr name="ringIsStroke" format="boolean" />    <!-- 进度颜色 -->    <attr name="ringProgressColor" format="color" />    <!-- 字体颜色 -->    <attr name="textColor" format="color" />    <!-- 字体大小 -->    <attr name="textSize" format="dimension" />    <!-- 是否显示中间的进度值 -->    <attr name="textIsDisplayable" format="boolean" />    <!-- 最大进度值 -->    <attr name="maxProgress" format="integer" />    <!-- 进度条的风格:实心或者空心 -->    <attr name="ringProgressStyle">        <enum name="STROKE" value="0" />        <enum name="FILL" value="1" />    </attr></declare-styleable>

2.布局文件

<com.wiggins.progresswheel.widget.RingProgressBar    android:id="@+id/mRingProgressBar"    android:layout_width="150dp"    android:layout_height="150dp"    android:layout_marginLeft="@dimen/margin_normal"    app:maxProgress="100"    app:ringColor="@color/blue"    app:ringIsStroke="false"    app:ringProgressColor="@color/orange"    app:ringWidth="7dp" />

3.java文件调用

mRingProgressBar.setCurrentProgress(63);

4.绘制视图

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    /**     * 绘制默认圆环     */    int centre = getWidth() / 2; // 获取圆心的x坐标    int radius = (int) (centre - mRingWidth / 2); // 圆环的半径    mRingPaint.setColor(mRingColor); // 圆环颜色    mRingPaint.setStrokeWidth(mRingWidth); // 圆环宽度    mRingPaint.setAntiAlias(true); // 消除锯齿    if (mRingIsStroke) {        mRingPaint.setStyle(Paint.Style.STROKE); // 设置空心    } else {        mRingPaint.setStyle(Paint.Style.FILL); // 设置实心    }    canvas.drawCircle(centre, centre, radius, mRingPaint); // 画出圆环    /**     * 绘制进度百分比     */    mTextPaint.setColor(mTextColor);    mTextPaint.setTextSize(mTextSize);    mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);    mTextPaint.setStyle(Paint.Style.FILL);    mTextPaint.setAntiAlias(true);    // 进度百分比    int percent = (int) (((float) mCurrentProgress / (float) mMaxProgress) * 100);    // 测量字体宽度    float textWidth = mTextPaint.measureText(percent + "%");    // 绘制的起点X轴坐标:画布宽度的一半 - 文字宽度的一半    int baseX = (int) (canvas.getWidth() / 2 - textWidth / 2);    // 绘制的起点Y轴坐标:画布高度的一半 - 文字总高度的一半    int baseY = (int) ((canvas.getHeight() / 2) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2));    if (mTextIsDisplayable && mRingProgressStyle == STROKE) {        canvas.drawText(percent + "%", baseX, baseY, mTextPaint);    }    /**     * 绘制进度的圆弧     */    mProgressPaint.setStrokeWidth(mRingWidth);    mProgressPaint.setColor(mRingProgressColor);    mProgressPaint.setAntiAlias(true);    RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限    switch (mRingProgressStyle) {        case STROKE: {            mProgressPaint.setStyle(Paint.Style.STROKE);            canvas.drawArc(oval, 270, 360 * mCurrentProgress / mMaxProgress, false, mProgressPaint); // 根据进度画圆弧            break;        }        case FILL: {            mProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);            if (mCurrentProgress != 0) {                canvas.drawArc(oval, 270, 360 * mCurrentProgress / mMaxProgress, true, mProgressPaint); // 根据进度画圆弧            }            break;        }    }}

项目地址 ☞ 传送门

0 0
原创粉丝点击