自定义SeekBar

实现效果

自定义SeekBar效果
Github传送门: https://github.com/drkingwater/TextSeekBar

实现功能

  1. 基本跟原生SeekBar一致
  2. 可以自定义Thumb大小
  3. 添加顶部文本显示

实现方法

  1. TextView + SeekBar组合
    大概就是更新SeekBar的时候计算当前进度百分比 * 宽度得到偏移量,设置TextView距离左边的偏移量。可以实现(话说一开始就是这样做的),就是要调来调去代码总有自己的想法,而且效果不是那么令人满意。
  2. 自定义View
    这不是废话吗~

实现思路

SeekBar可以通过progressDrawable来设置background、progress、secondProgress,就想要尽量跟原生SeekBar保持用法上一致,即自定义的SeekBar也要可以设置progressDrawable,大概看了SeekBar源码,发现SeekBar是在ProgressBar的基础上多画了个Thumb~~
那直接继承ProgressBar,再多画个Thumb和文本就行了
在这里插入图片描述
实际上没搞成~
——————————
那就只能自定义了,又粗略看了下ProgressBar源码,主要是看如何去画background、progress这些,于是发现了这个
progressDrawable
难道Drawable也可以直接draw(原谅我基础薄弱),果断百度了一波:先用drawable.setBounds()设置大小
然后drawable.draw(canvas)

还有这种操作。。。这下background知道如何操作了,脑子里马上就冒出progress操作法:当前进度 / 总进度获取百分比,动态设置drawable.setBounds()

想想不是这么个事:progress是按进度慢慢显示完,也就是可以控制显示多少,而不是控制整个progress的长度,于是继续翻~

发现了这个:d = (LayerDrawable) d.findDrawableByLayerId(id)
感觉有什么东西要出来了~,又发现到自定义drawable里

background和progress的drawable类型是不同的(之前拷贝粘贴没注意过),progress多了个<clip>可不就ClipDrawable吗!那不是可以这样:(ClipDrawable) d.findDrawableByLayerId(android.id.progress)
————————
综上:

  1. 画background: Drawable.setBounds()设置位置大小,然后draw(canvas)
  2. 画progress : ClipDrawable.setLevel()

知道了这些之后就简单了

具体实现

实际实现的时候应该要为两边的预留空间来处理Thumb和Text,即实际的控件范围应该是这样的

于是background的范围应该是这样计算(progress同样)

thumb的初始范围是这样:

当然Thumb要动起来,left还要加上进度占比

总体流程如下:

最后处理手势:

  1. 判断手势落点是否在Thumb范围内
  2. 滑动时用x坐标实时计算占总宽度的百分比 * maxProgress来设置progress
/**
     * 判断落点是否在thumb范围内
     *
     * @param event
     * @return
     */
    private boolean inThumbBound(MotionEvent event) {
        //(当前进度+bgLeft) +- thumbWidth / 2
        float center = mBackgroundLeft + getFraction(mProgress) * mBackgroundWidth;
        float x = event.getX();
        return x >= center - mThumbWith / 2 && x <= center + mThumbWith / 2;
    }

    /**
     * 判断滑动是否在SeekBar范围内
     *
     * @param event
     * @return
     */
    private boolean checkProgressBound(MotionEvent event) {
        float x = event.getX();
        return x >= (mBackgroundLeft - mThumbLeft) && x <= mBackgroundLeft + mBackgroundWidth + mThumbRight;
    }

    private int getProgress(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        float availableWidth = mBackgroundWidth;
        float fraction = (x - mBackgroundLeft) / availableWidth;
        fraction = Math.max(0, fraction);
        fraction = Math.min(fraction, 1);
        return (int) (fraction * getMax());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (inThumbBound(event)) {
                    mIsDragging = true;
                    if (mOnSeekBarChangeListener != null) {
                        mOnSeekBarChangeListener.onStartTrackingTouch(this);
                    }
                    return true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mIsDragging && checkProgressBound(event)) {
                    setProgress(getProgress(event));
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mOnSeekBarChangeListener != null && mIsDragging) {
                    mOnSeekBarChangeListener.onStopTrackingTouch(this);
                }
                mIsDragging = false;
                break;
        }

        return super.onTouchEvent(event);
    }

———————— Over ——————————

发布了19 篇原创文章 · 获赞 25 · 访问量 5603

猜你喜欢

转载自blog.csdn.net/pxq10422/article/details/90216567