自定義thumb的Seekbar



import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;


public class SeekBarWithBubbleView extends View {
    private Context mContext;
    private Paint mSeekBarBgPaint;
    private Paint mBubbleViewPaint;
    private Bitmap mBubbleBitmap;
    private Bitmap mSeekBarBackground;

    private float mMin = 0; // min
    private float mMax = 100; // max
    private float mNowProgress = mMin;

    private int mViewWidth;// 获取到视图宽度
    private int mViewHeight;// 视图高度
    private int mBubbleWidth; // 气泡宽度
    private int mBubbleHeight;// 气泡高度

    private float mBubbleViewX; // 气泡的X坐标
    private float mBubbleViewY;// 气泡的Y坐标

    private boolean mDisabledMode = false;// 是否为亮度自动模式,自动模式不可点击

    private float mProgressExtraWidth = 0; //坐标预留

    private OnProgressChangedListener mProgressListener; // 进度change监听

    public void setProgressChangeListener(OnProgressChangedListener mProgressListener) {
        this.mProgressListener = mProgressListener;
    }

    public SeekBarWithBubbleView(Context context) {
        super(context);
    }

    public SeekBarWithBubbleView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        initView(attrs);
    }

    public SeekBarWithBubbleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 初始化数据
     *
     * @param attrs
     */
    private void initView(AttributeSet attrs) {
        if (null == attrs) {
            return;
        }
        TypedArray ta = mContext.obtainStyledAttributes(attrs, R.styleable.SeekBarWithBubbleView);
        mMax = ta.getInt(R.styleable.SeekBarWithBubbleView_seekBarMax, 100);
        mMin = ta.getInt(R.styleable.SeekBarWithBubbleView_seekBarMin, 0);
        mNowProgress = ta.getFloat(R.styleable.SeekBarWithBubbleView_nowProgress, mMin);
        ta.recycle();

        mSeekBarBgPaint = new Paint();
        mSeekBarBgPaint.setAntiAlias(true);
        mSeekBarBgPaint.setStrokeCap(Paint.Cap.ROUND);
        mSeekBarBgPaint.setTextAlign(Paint.Align.CENTER);
        mSeekBarBgPaint.setStrokeWidth(4);

        mBubbleViewPaint = new Paint();
        mBubbleViewPaint.setAntiAlias(true);
        mBubbleViewPaint.setStrokeCap(Paint.Cap.ROUND);
        mBubbleViewPaint.setTextAlign(Paint.Align.CENTER);
        mBubbleViewPaint.setFakeBoldText(true);
        mBubbleViewPaint.setTextSize(23);
        mBubbleViewPaint.setColor(ContextCompat.getColor(mContext, R.color.tv_setting_bubble_text));
        mBubbleViewPaint.setTextAlign(Paint.Align.CENTER);
        setFocusable(true);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mViewWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        mViewHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        mBubbleBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_common_seek_bar_thumb_enable);
        mBubbleWidth = mBubbleBitmap.getWidth();
        mBubbleHeight = mBubbleBitmap.getHeight();
        mProgressExtraWidth = (float) (mBubbleWidth / 2.0);
        // 获取气泡的中心点
        setProgressValue((int) mNowProgress);
        //mBubbleViewX = (float) (mProgressExtraWidth);
        mBubbleViewY = (float) (57f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        setLayerType(LAYER_TYPE_SOFTWARE, null);//对单独的View在运行时阶段禁用硬件加速

        // 画出Seekbar背景
        if (!mDisabledMode) {
            mSeekBarBackground = BitmapFactory.decodeResource(getResources(), R.drawable.bg_seekbar_background_enabled);
        } else {
            mSeekBarBackground = BitmapFactory.decodeResource(getResources(), R.drawable.bg_seekbar_background_disabled);
        }
        canvas.drawBitmap(mSeekBarBackground, 0, 57, mSeekBarBgPaint);

        // 绘制气泡背景图
        if (!mDisabledMode) {
            mBubbleBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_common_seek_bar_thumb_enable);
        } else {
            mBubbleBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_common_seek_bar_thumb_disabled);
        }
        canvas.drawBitmap(mBubbleBitmap, mBubbleViewX - mProgressExtraWidth, 0, mBubbleViewPaint);

        if (!mDisabledMode) {
            // 画笔设置了Align为Center,就不用减一半宽度了
            String nowProgress = String.valueOf((int) mNowProgress);
            if (mNowProgress >= 1 && mMin < 0) {
                nowProgress = "+" + nowProgress;
            }
            canvas.drawText(nowProgress, mBubbleViewX, 25, mBubbleViewPaint);
        }
    }

    public interface OnProgressChangedListener {

        void onProgressChanged(SeekBarWithBubbleView bubbleSeekBar, int progress, boolean fromUser);

        void onStartChangeProgress(SeekBarWithBubbleView bubbleSeekBar, int progress);

        void onStopChangeProgress(SeekBarWithBubbleView bubbleSeekBar, int progress, boolean fromUser);
    }

    // 防止父类响应事件
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        getParent().requestDisallowInterceptTouchEvent(true);
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mDisabledMode) {
            return true;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                updateBubbleViewPosition(event.getX());
                if (null != mProgressListener) {
                    mProgressListener.onStartChangeProgress(this, (int) mNowProgress);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                updateBubbleViewPosition(event.getX());
                if (null != mProgressListener) {
                    mProgressListener.onProgressChanged(this, (int) mNowProgress, true);
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                //setProgressValue((int) mNowProgress);
                if (null != mProgressListener) {
                    if (mNowProgress < mMin) {
                        mNowProgress = mMin;
                    }
                    if (mNowProgress > mMax) {
                        mNowProgress = mMax;
                    }
                    mProgressListener.onStopChangeProgress(this, (int) mNowProgress, true);
                }
                break;
            default:
                break;
        }
        invalidate();
        return true;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (null != mBubbleBitmap) {
            mBubbleBitmap.recycle();
            mBubbleBitmap = null;
        }
        if (null != mSeekBarBackground) {
            mSeekBarBackground.recycle();
            mSeekBarBackground = null;
        }
    }

    /**
     * 更新气泡位置及进度
     *
     * @param touchX
     */
    private void updateBubbleViewPosition(float touchX) {
        if (touchX < mProgressExtraWidth) {
            mBubbleViewX = mProgressExtraWidth;
            mNowProgress = mMin;
        } else if (touchX > mViewWidth - mProgressExtraWidth) {
            mBubbleViewX = (mViewWidth - mProgressExtraWidth);
            mNowProgress = mMax;
        } else {
            mBubbleViewX = touchX;
            mNowProgress = (mBubbleViewX - mProgressExtraWidth) / ((mViewWidth - 2 * mProgressExtraWidth) / (mMax - mMin)) + mMin;
        }
    }

    /**
     * 设置进度
     *
     * @param progress
     */
    public void setProgressValue(int progress) {
        if (progress < mMin) {
            mNowProgress = mMin;
        } else if (progress > mMax) {
            mNowProgress = mMax;
        } else {
            mNowProgress = progress;
        }
        mBubbleViewX = (mNowProgress - mMin) * ((mViewWidth - 2 * mProgressExtraWidth) / (mMax - mMin)) + mProgressExtraWidth;
        invalidate();
    }

    /**
     * 设置模式
     *
     * @param disabledMode
     */
    public void setMode(boolean disabledMode) {
        this.mDisabledMode = disabledMode;
        invalidate();
    }
}

icon_common_seek_bar_thumb_enable

icon_common_seek_bar_thumb_disabled

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值