Android 带气泡的ProgressBar|8月更文挑战

1,493 阅读2分钟

背景

需求改了,上一个样式的进度条不要了! 对, 需求就是改的这么快这么突然, 能怎么办继续改呗

效果

Kapture 2021-08-02 at 22.35.11.gif

步骤

1.获取控件的宽高

还是继续在onMeasure中获取控件宽高

PS:如果使用onMeasure获取控件宽高就必须手动调用setMeasuredDimension方法设置宽高否则会报错

@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //获取控件宽高
    width = MeasureSpec.getSize(widthMeasureSpec);
    height = MeasureSpec.getSize(heightMeasureSpec);
    setMeasuredDimension(width, height);
}

2.获取文字宽度

由于要画文字,就会涉及到获取文字宽度的问题,这里使用measureText()方法获取文字的实际宽度(如果涉及到Padding,则需要按照实际情况加上左右的距离)

float textWidth = paintWave.measureText(text);

3.绘制文字边界问题

在控件中绘制文字特别是这个文字还会跟着进度走, 就肯定会涉及到文字画出边界的问题, 这里就简单处理一下,条件是 X轴坐标 + 文字高度 是否大于控件宽度

int progress = getProgress();
float location = width / 100 * progress;
float textWidth = paintWave.measureText(progress + "%");
//如果文字初始坐标小于0,则x轴赋值为文字宽度,因为在绘制文字是会减去文字的宽度
if ((location - textWidth) <= 0){
    location = textWidth;
}
//如果文字移动坐标大于控件宽度,则x轴赋值为控件宽度,因为在绘制文字是会减去文字的宽度
if ((location + textWidth) >= width){
    location = width;
}
//此处x轴减文字宽度是为了防止在进度为100时文字画出控件边界
canvas.drawText(progress + "%", location - textWidth, (height >> 1) + paintWave.getTextSize() * 3, paintWave);

4.绘制圆点滑块

绘制圆点滑块时的注意事项和逻辑同绘制文字, 都是要处理边界问题

image.png

5.控制文字进度位置

考虑到可能由于需求问题, 导致进度文字有可能出现在进度条上方或者下方,于是加了个属性进行控制

<declare-styleable name="SliderProgressBarStyle">
    //文字位置
    <attr name="textLocation">
        <enum name="bottom" value="0"/>
        <enum name="top" value="1"/>
    </attr>
    //是否显示气泡
    <attr name="isShowBubble" format="boolean" />
</declare-styleable>

文字位置默认是在进度条下方,气泡默认不显示, 根据设置的文字位置去计算对应的Y轴坐标

if (textLocation == 0){
    textY = (height >> 1) - paintWave.getTextSize()  * 2;
}else{
    textY = (height >> 1) + paintWave.getTextSize() * 2;
}

6. 气泡

处理气泡时需要注意几点

1.本身气泡图标中的边距

2.绘制气泡时两边可能会超出控件边界

3.绘制气泡时坐标位置

if (isShowBubble) {
    //防止在边界时气泡绘制有问题, 做了一个控件最大宽度判断, 是否为气泡改变方向
    if ((location + bubbleLeftWidth) >= width){
        canvas.drawText(progress + "%", location - bubbleRightWidth /2 - textWidth / 2, height / 2 - bubbleRightHeight / 2, paintWave);
        canvas.drawBitmap(bubbleRight, location - bubbleRightWidth , height / 2 - bubbleRightHeight, null);
    }else {
        canvas.drawText(progress + "%", location + bubbleLeftWidth / 4 - textWidth / 2, height / 2 - bubbleLeftHeight / 2, paintWave);
        canvas.drawBitmap(bubbleLeft, location - bubbleLeftWidth / 4, height / 2 - bubbleLeftHeight, null);
    }
}else {
    //此处x轴减文字宽度是为了防止在进度为100时文字画出控件边界
    canvas.drawText(progress + "%", location - textWidth, textY, paintWave);
}

项目地址