SeekBar使用自定义Drawable作为thumb
文章目录
工作中遇到一个需求,要在seekBar的thumb上显示文本,并且thumb还有特定的样式,如下图。考虑了一下之后,决定采用自定义Drawable作为thumb drawable。
![]()
一、实现代码
public class LoadingTextDrawable extends Drawable implements DrawBufferIndicatorHelper.Callback {
private final DrawBufferIndicatorHelper drawHelper;
private Paint paint;
private final RectF rectF;
private Context context;
private int dp2;
public LoadingTextDrawable(Context context) {
this.context = context;
paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(DisplayUtil.dip2px(context, 12));
paint.setColor(Color.BLACK);
rectF = new RectF();
drawHelper = new DrawBufferIndicatorHelper(this);
drawHelper.show(false);
}
public void loading(boolean loading) {
drawHelper.show(loading);
}
/**
* drawable边界改变
*
* @param bounds
*/
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
dp2 = DisplayUtil.dip2px(context, 2);
int dp50 = DisplayUtil.dip2px(context, 50);
int dp30 = DisplayUtil.dip2px(context, 12);
rectF.left = bounds.left + dp50;
rectF.right = bounds.right - dp50;
rectF.top = bounds.top + dp30;
rectF.bottom = bounds.bottom - dp30;
drawHelper.setSize((int) (Math.abs(rectF.height()) / 2f));
invalidate();
}
/**
* 绘制
*
* @param canvas
*/
@Override
public void draw(@NonNull Canvas canvas) {
Log.d("MyDrawable", "drawable draw...");
paint.setColor(Color.WHITE);
float width = Math.abs(rectF.width());
canvas.drawRoundRect(rectF, width / 4, width / 4, paint);
//绘制时间文字
String string = "00:10/06:22";
paint.setColor(Color.BLACK);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float bottomLineY = rectF.centerY() - (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.top;
float x = (rectF.width() - paint.measureText(string)) / 2 + rectF.left + drawHelper.getSize();
canvas.drawText(string, x, bottomLineY, paint);
//绘制loading
canvas.save();
//loading怎么计算不能居中,加2dp视觉上居中
canvas.translate(rectF.right + drawHelper.getSize(), rectF.centerY() + rectF.height() / 2 + drawHelper.getSize() / 2 + dp2);
drawHelper.draw(canvas);
canvas.restore();
}
/**
* 设置画笔透明度
*
* @param alpha
*/
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
invalidateSelf();
}
/**
* 设置画笔颜色过滤器
*
* @param colorFilter
*/
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
invalidateSelf();
}
/**
* 设置drawable透明类型
*/
/**
* @return
*/
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@Override
public void invalidate() {
if (getCallback() == null) {
Log.d("MyDrawable", "invalidateSelf null");
} else {
Log.d("MyDrawable", "invalidateSelf");
}
//刷新drawable
invalidateSelf();
}
}
二、细节,以及问题
1、onBoundsChange
拖动seekbar的时候,seekBar会调用thumb drawable的setBounds方法。onBoundsChange回调的时候,就是自定义drawable的绘制区域发生改变,如果不在onBoundsChange回调的时候调整绘制的位置,会导致seekBar拖动的时候thumb在原地。
2、drawable刷新
drawable是依附于view显示的,它定义的是绘制的方式,而绘制一般是由view来做的。
view在设置drawable的时候一般会同时设置一个callback,当调用drawable的invalidateSelf时,会通过callback回调view的invalidateDrawable。
但是自定义drawable用在seekbar上时,调用invalidateSelf没有刷新drawable。
可以在重载invalidateDrawable,在调用此方法之前执行
postInvalidateOnAnimation()
3、SeekBar两边有空隙
可以设置seekbar布局
android:paddingStart="0dp"
,
android:paddingEnd="0dp"
4、SeekBar按住的时候有一小块圆形阴影
android:thumb="@null"
版权声明:本文为SywCache原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。