SeekBar使用自定义Drawable作为thumb

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"

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
要实现SeekBarThumbDrawable同步,可以通过设置SeekBarThumb来实现。具体实现方法如下: 1. 首先,为SeekBar设置一个Thumb: ```java seekBar.setThumb(getResources().getDrawable(R.drawable.thumb)); ``` 2. 接着,在ThumbDrawable中添加对应的Drawable状态: ```xml <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/thumb_pressed"/> <item android:drawable="@drawable/thumb_normal"/> </selector> ``` 其中,thumb_pressed和thumb_normal是两个Drawable资源,分别代表Thumb在按下和未按下时的状态。 3. 最后,在SeekBar的OnSeekBarChangeListener的方法中,根据SeekBar的进度来更新ThumbDrawable状态: ```java seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { Drawable thumbDrawable = seekBar.getThumb(); if (thumbDrawable instanceof StateListDrawable) { StateListDrawable stateListDrawable = (StateListDrawable) thumbDrawable; stateListDrawable.setState(new int[]{android.R.attr.state_enabled}); if (progress == 0) { stateListDrawable.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_first}); } else if (progress == 100) { stateListDrawable.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_last}); } else { stateListDrawable.setState(new int[]{android.R.attr.state_enabled}); } } } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); ``` 这段代码中,根据SeekBar的进度来更新ThumbDrawable状态,如果进度为0,则设置为state_first状态,如果进度为100,则设置为state_last状态,否则设置为state_enabled状态。这样就可以实现SeekBarThumbDrawable同步了。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值