IndicateProgressBar 带指示器的ProgressBar进度条

github地址: https://github.com/w296365959/IndicateProgressBar

同事给的效果图索要个这样的进度条,趁着空闲时间,就做了这个
IndicateProgressBar ,这是一个简单的自定义View,带指示器的进度条。
如有 不足之处,尽情指出
转载请标明出处:
http://blog.csdn.net/w296365959/article/details/78496985

效果图:

IndicateProgressBar

整体思路:
先把底部背景条给画出,就是一个带圆角的矩形;
接着我们画进度条,我们可以看到进度条也是一个带圆角的矩形,同理,我们一样只要画出一个带圆角的矩形就可以了,只不过这个矩形长度是可以变化的而已,矩形左边x坐标为0,右边x坐标是背景条长度*进度比例, 我们进度条颜色是随着进度改变而渐变的,这也简单,可以直接使用Shader 来设置渐变色。这样进度画好了;
接着,画进度条的指示器,指示器室友3部分组成的,一个外框+内部填充+一个进度文本,
这都是一样 ,画个矩形就可以了,只不过给画笔颜色不同,最后在画一个文本,这文本写在矩形框内,具体数据可以自己调试。

关键代码分析:
//在ondraw里面画出进度条背景,进度,以及指示器

       width = getWidth() - (int) (indicateTextPaint.measureText(max + "%") + defaultMargin);//进度条最大宽度,减去文本长度+defaultMargin 是为了放置指示器位置,
       height = getHeight();
        //画背景
        RectF backRectF = new RectF(0, height * 2 / 5, width, height * 3 / 5);
        canvas.drawRoundRect(backRectF, radius, radius, backPaint);

        //画进度
        RectF progressRectF = new RectF(0, height * 2 / 5, width * getScale(), height * 3 / 5);
        Shader shader = new LinearGradient(0, 0, 400, 400, startProgressColor, Color.RED, Shader.TileMode.REPEAT);//渐变
        progressPaint.setShader(shader);
        canvas.drawRoundRect(progressRectF, radius, radius, progressPaint);

        //画指示器边框
        float left = getScale() * width;
        float right = getScale() * width + indicateTextPaint.measureText(max + "%") + defaultMargin;

        if (left <= 0f) {//当指示器最左边不在控件范围时,强制左边界=0
            left = 0f;
            right = indicateTextPaint.measureText(max + "%") + defaultMargin;
        }
        if (left >= width) {//当指示器左边界超出控件范围时,强制左边界=进度最大长度
            left = width;
            right = width + indicateTextPaint.measureText(max + "%") + defaultMargin;
        }
        RectF indicatorRectF = new RectF(left, height / 5, right, height * 4 / 5);
        indicateBackPaint.setColor(textColor);
        canvas.drawRoundRect(indicatorRectF, indicatorRadius, indicatorRadius, indicateBackPaint);
        //画指示器内部为白色
        RectF indicatorContentRectF = new RectF(left + 2, height / 5 + 2, right - 2, height * 4 / 5 - 2);
        indicateBackPaint.setColor(Color.WHITE);
        canvas.drawRoundRect(indicatorContentRectF, indicatorRadius, indicatorRadius, indicateBackPaint);

        //画指示器文本
        float textX = indicatorContentRectF.centerX() - indicateTextPaint.measureText(progressText) / 2;
        float textY = backRectF.centerY() + height / 9;
        canvas.drawText(progressText, textX, textY, indicateTextPaint);

然后,在onTouchEvent里控制 手指拖动进度条,isCanTouch可以控制是否可以拖动

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isCanTouch) {//开启可手动拖动
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    break;
                case MotionEvent.ACTION_MOVE:
                    x = event.getX();//基于控件的坐标
                /*float rawX = event.getRawX();//基于屏幕的坐标
                Log.i(TAG, "x==: " + x);
                Log.i(TAG, "rawX==: " + rawX);
                Log.i(TAG, "width==: " + width);
                Log.i(TAG, "height==: " + height);*/
                    int count = (int) x * 100 / width;
                    if (count > 100) {
                        count = 100;
                    } else if (count < 0) {
                        count = 0;
                    }
                    progressText = count + "%";
                    setProgress(count);
                    Log.i(TAG, "progressText==: " + progressText);
                    invalidate();//主线程中调用刷新
                    // postInvalidate();//可在非UI线程中调用刷新,底层还是使用handler发送到主线程刷新重绘

                    break;
                case MotionEvent.ACTION_UP:
                    break;
            }

            return true;
        }else {
            return super.onTouchEvent(event);
        }
    }

代码简单易懂,完整代码如下:


/**
 * Author: wangzhongming<br/>
 * Date :  2017/11/8 11:33 </br>
 * Summary: 带指示器的进度条
 */

public class IndicateProgressBar extends View {

    private float x = 10;
    private String progressText = "0%";
    private static final String TAG = IndicateProgressBar.class.getSimpleName();
    private int width;
    private int height;

    private Paint backPaint;
    private Paint progressPaint;
    private Paint indicateTextPaint;
    private Paint indicateBackPaint;
    private int radius = 10; //进度条四个角的角度px
    private int indicatorRadius = 32; //进度指示器四个角的角度px
    private int defaultMargin = 30; //进度指示器默认多一点长度
    private int max = 100;//进度最大值
    private int progress = 0;//进度0-100
    private boolean isCanTouch = true;//进度条是否可以手动拖动
    private int startProgressColor = 0xfff29310;
    private int textColor = 0xffef4f37;
    private int gray = 0xfff5f5f5;

    public IndicateProgressBar(Context context) {
        this(context, null);
    }

    public IndicateProgressBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    private void initView() {
//        Android在用画笔的时候有三种Style,分别是
//        Paint.Style.STROKE 只绘制图形轮廓(描边)//空心效果
//        Paint.Style.FILL 只绘制图形内容
//        Paint.Style.FILL_AND_STROKE 既绘制轮廓也绘制内容

        //Paint.ANTI_ALIAS_FLAG 抗锯齿
        //进度条背景画笔
        backPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        backPaint.setColor(gray);
        backPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        //进度条进度画笔
        progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        progressPaint.setStyle(Paint.Style.FILL);

        //进度条指示器框画笔
        indicateBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        indicateBackPaint.setColor(textColor);
        indicateBackPaint.setTextSize(32);

        //进度条指示器文本画笔
        indicateTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        indicateTextPaint.setColor(textColor);

    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        width = getWidth() - (int) (indicateTextPaint.measureText(max + "%") + defaultMargin);
        height = getHeight();
//画背景
        RectF backRectF = new RectF(0, height * 2 / 5, width, height * 3 / 5);
        canvas.drawRoundRect(backRectF, radius, radius, backPaint);

        //画进度
        RectF progressRectF = new RectF(0, height * 2 / 5, width * getScale(), height * 3 / 5);
        Shader shader = new LinearGradient(0, 0, 400, 400, startProgressColor, Color.RED, Shader.TileMode.REPEAT);//渐变
        progressPaint.setShader(shader);
        canvas.drawRoundRect(progressRectF, radius, radius, progressPaint);

        //画指示器边框
        float left = getScale() * width;
        float right = getScale() * width + indicateTextPaint.measureText(max + "%") + defaultMargin;

        if (left <= 0f) {
            left = 0f;
            right = indicateTextPaint.measureText(max + "%") + defaultMargin;
        }
        if (left >= width) {
            left = width;
            right = width + indicateTextPaint.measureText(max + "%") + defaultMargin;
        }
        RectF indicatorRectF = new RectF(left, height / 5, right, height * 4 / 5);
        indicateBackPaint.setColor(textColor);
        canvas.drawRoundRect(indicatorRectF, indicatorRadius, indicatorRadius, indicateBackPaint);
        //画指示器内部为白色
        RectF indicatorContentRectF = new RectF(left + 2, height / 5 + 2, right - 2, height * 4 / 5 - 2);
        indicateBackPaint.setColor(Color.WHITE);
        canvas.drawRoundRect(indicatorContentRectF, indicatorRadius, indicatorRadius, indicateBackPaint);

        //画指示器文本
        float textX = indicatorContentRectF.centerX() - indicateTextPaint.measureText(progressText) / 2;
        float textY = backRectF.centerY() + height / 9;
        canvas.drawText(progressText, textX, textY, indicateTextPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isCanTouch) {//开启可手动拖动
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    break;
                case MotionEvent.ACTION_MOVE:
                    x = event.getX();//基于控件的坐标
                /*float rawX = event.getRawX();//基于屏幕的坐标
                Log.i(TAG, "x==: " + x);
                Log.i(TAG, "rawX==: " + rawX);
                Log.i(TAG, "width==: " + width);
                Log.i(TAG, "height==: " + height);*/
                    int count = (int) x * 100 / width;
                    if (count > 100) {
                        count = 100;
                    } else if (count < 0) {
                        count = 0;
                    }
                    progressText = count + "%";
                    setProgress(count);
                    Log.i(TAG, "progressText==: " + progressText);
                    invalidate();//主线程中调用刷新
                    // postInvalidate();//可在非UI线程中调用刷新,底层还是使用handler发送到主线程刷新重绘

                    break;
                case MotionEvent.ACTION_UP:
                    break;
            }

            return true;
        }else {
            return super.onTouchEvent(event);
        }
    }

    /**
     * 是否开启拖动有效
     * 默认可以手动拖动
     *
     * @param isOpen true开启可以手动拖动
     */
    public void setCanTouch(boolean isOpen) {
        isCanTouch = isOpen;
    }


    /**
     * 设置进度,getScale()内会调用
     *
     * @param progress 0-100 ,最大进度默认100
     */
    public void setProgress(int progress) {
        this.progress = progress;
    }

    /**
     * 设置进度,getScale()内会调用
     *
     * @param progress 进度 0-100
     * @param max      最大进度 ,不写则默认100
     */
    public void setProgress(int progress, int max) {
        this.progress = progress;
        this.max = max;
    }

    /**
     * 进度显示百分数
     *
     * @param strText 如写 70%
     */
    private void setProgeressText(String strText) {
        progressText = strText;
    }

    /**
     * 进度比例小数
     *
     * @return
     */
    private float getScale() {
        float scale;
        if (max == 0) {
            scale = 0;
        } else {
            scale = (float) progress / (float) max;
        }
        setProgeressText((int) (scale * 100) + "%");
        return scale;
    }


}

好了,一个简单的带指示器的进度条完成了!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值