带下标的SeekBar


/**
 * 带下标的seekBar
 */
public class CustomSeekbar extends View {

    private final String TAG = "CustomSeekbar";

    private Paint mPaint;
    private Paint mTextPaint;
    private Bitmap mThumb;
    private int mThumbOffset = 0; //头尾的偏移
    private int mProgress = 2;

    private int mTextSize;
    private int mTextSpace = 20;//track与文字之间的距离
    private int mTextColor = Color.parseColor("#969696");
    private Rect mRectText;
    private List<String> mTitles;

    private int mTrackHeight = 6;//track高度
    private int mTrackColor = Color.GRAY;
    private int mTrackOffset = 0; //头尾偏移
    private int mProgressTrackColor = Color.BLACK;

    private OnProgressChangedListener mOnProgressChangedListener;

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

    public CustomSeekbar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomSeekbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mPaint = new Paint(Paint.DITHER_FLAG);
        mPaint.setAntiAlias(true);//锯齿不显示
        mTextPaint = new Paint(Paint.DITHER_FLAG);
        mTextPaint.setAntiAlias(true);
        mRectText = new Rect();

        init(context, attrs, defStyleAttr);

    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomSeekbar);
        mTextSpace = a.getDimensionPixelSize(R.styleable.CustomSeekbar_csb_text_space, getFontHeight() * 2);
        mTextColor = a.getColor(R.styleable.CustomSeekbar_csb_text_color, Color.BLUE);
        mTextSize = a.getDimensionPixelSize(R.styleable.CustomSeekbar_csb_text_size, 10);
        mThumb = BitmapFactory.decodeResource(getResources(), a.getResourceId(R.styleable.CustomSeekbar_csb_thumb, R.drawable.group_set_thumb));
        mTrackHeight = a.getDimensionPixelOffset(R.styleable.CustomSeekbar_csb_track_height, dp2px(mTrackHeight));
        mTrackColor = a.getColor(R.styleable.CustomSeekbar_csb_track_color, mTrackColor);
        mProgressTrackColor = a.getColor(R.styleable.CustomSeekbar_csb_progress_track_color, mProgressTrackColor);
        mProgress = a.getInteger(R.styleable.CustomSeekbar_csb_progress, 0);
        mTrackOffset = a.getDimensionPixelOffset(R.styleable.CustomSeekbar_csb_track_offset, 0);
        mThumbOffset = a.getDimensionPixelOffset(R.styleable.CustomSeekbar_csb_thumb_offset , 0);
        int dataId = a.getResourceId(R.styleable.CustomSeekbar_csb_data, 0);
        if (dataId != 0) {
            String[] data = getResources().getStringArray(dataId);
            initData(Arrays.asList(data));
        } else {
            initData(null);
        }
        a.recycle();

    }

    /**
     * 实例化后调用,设置bar的段数和文字
     */
    public void initData(List<String> data) {
        if (data != null) {
            mTitles = data;
        } else {
            mTitles = new ArrayList<>();
            mTitles.add("低");
            mTitles.add("中");
            mTitles.add("高");
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int width = widthSize;
        int height = getPaddingTop() + getPaddingBottom() + Math.max(getThumbHeight(), mTrackHeight)
                + mTextSpace + getFontHeight();

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //track的起点
        int startX = getPaddingLeft() + getThumbHeight() / 2;
        int startY = getPaddingTop() + (getThumbHeight() > mTrackHeight ? getThumbHeight() - mTrackHeight : 0) / 2;

        drawTrack(canvas, startX, startY);
        drawProgressTrack(canvas, startX, startY);
        drawThumb(canvas, startX, startY);
        drawText(canvas, startX, startY);
    }

    private void drawTrack(Canvas canvas, int startX, int startY) {
        int endX = getWidth() - getPaddingRight() - getThumbWidth() / 2 + mTrackOffset;
        int y = startY;
        mPaint.setColor(mTrackColor);
        canvas.drawRect(startX - mTrackOffset, startY, endX, startY + mTrackHeight, mPaint);

        canvas.drawCircle(startX - mTrackOffset, y + mTrackHeight / 2, mTrackHeight / 2, mPaint);
        canvas.drawCircle(endX, y + mTrackHeight / 2, mTrackHeight / 2, mPaint);
    }

    private void drawProgressTrack(Canvas canvas, int startX, int startY) {
        if (getProgress() == 0) {
            return;
        }

        mPaint.setColor(mProgressTrackColor);
        int endX = startX + getProgress() * getItemWidth();
        if (getProgress() == getMax()) {
            endX += mTrackOffset;
        }
        int y = startY;
        canvas.drawRect(startX - mTrackOffset, startY, endX, startY + mTrackHeight, mPaint);

        canvas.drawCircle(startX - mTrackOffset, y + mTrackHeight / 2, mTrackHeight / 2, mPaint);
        canvas.drawCircle(endX, y + mTrackHeight / 2, mTrackHeight / 2, mPaint);
    }

    private void drawThumb(Canvas canvas, int startX, int startY) {
        int x = startX + getProgress() * getItemWidth() - getThumbWidth() / 2;
        int y = getThumbHeight() > mTrackHeight ? 0 : (mTrackHeight - getThumbHeight()) / 2;
        if (getProgress() == 0) {
            x -= mThumbOffset;
        } else if (getProgress() == getMax()) {
            x += mThumbOffset;
        }
        canvas.drawBitmap(mThumb, x, y, mPaint);
    }

    private void drawText(Canvas canvas, int startX, int startY) {

        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextSize(mTextSize);
        for (int i = 0; i <= getMax(); i++) {
            String title = mTitles.get(i);
            if (title == null || title.isEmpty()) {
                continue;
            }
            int x = startX + i * getItemWidth() - getTextWidth(title) / 2;
            int y = getPaddingTop() + Math.max(getThumbHeight(), mTrackHeight) + mTextSpace + getFontHeight() / 2;
            canvas.drawText(title, x, y, mTextPaint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:

                break;
            case MotionEvent.ACTION_MOVE:
                int progress = findProgress(event.getX(), event.getY());
                if (progress < 0) {
                    break;
                }
                setProgress(progress);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (mOnProgressChangedListener != null) {
                    mOnProgressChangedListener.onProgressChanged(this, getProgress());
                }
                break;
        }
        return true;
    }

    private int findProgress(float x, float y) {
        Log.d(TAG, "findProgress: x: " + x + ", y: " + y);
        if (x <= getLeft() + getPaddingLeft() + getThumbWidth() / 2) {
            return 0;
        } else if (x >= getRight() - getPaddingRight() - getThumbWidth() / 2) {
            return getMax();
        }

        if (y >= getBottom() - getPaddingBottom() - getFontHeight()) {
            return -1;
        }

        int progress = (int) ((x - getLeft() - getPaddingLeft() - getThumbWidth() / 2) / getItemWidth() + 0.5);
        progress = progress > getMax() ? getMax() : progress;
        return progress;
    }

    public int getMax() {
        if (mTitles == null || mTitles.size() <= 1) {
            return 0;
        }
        return mTitles.size() - 1;
    }

    //设置进度
    public void setProgress(int progress) {
        mProgress = progress > getMax() ? getMax() : progress;
        invalidate();
    }

    public int getProgress() {
        return mProgress;
    }

    private int getThumbWidth() {
        if (mThumb == null || mThumb.isRecycled()) {
            return 0;
        }
        return mThumb.getWidth();
    }

    private int getThumbHeight() {
        if (mThumb == null || mThumb.isRecycled()) {
            return 0;
        }
        return mThumb.getHeight();
    }

    private int getItemWidth() {
        return (getWidth() - getPaddingLeft() - getPaddingRight() - getThumbWidth()) / (mTitles.size() - 1);
    }

    private int getFontHeight() {
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.getTextBounds("w", 0, 1, mRectText);
        return mRectText.height();
    }

    private int getTextWidth(String text) {
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.getTextBounds(text, 0, text.length(), mRectText);
        return mRectText.width();
    }

    public OnProgressChangedListener getOnProgressChangedListener() {
        return mOnProgressChangedListener;
    }

    public void setOnProgressChangeListener(OnProgressChangedListener mOnProgressChangedListener) {
        this.mOnProgressChangedListener = mOnProgressChangedListener;
    }


    public interface OnProgressChangedListener {
        void onProgressChanged(CustomSeekbar seekBar, int progress);
    }

    static int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                Resources.getSystem().getDisplayMetrics());
    }

    static int sp2px(int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                Resources.getSystem().getDisplayMetrics());
    }
}
    <declare-styleable name="CustomSeekbar">
        <attr name="csb_data" format="reference" />
        <attr name="csb_text_color" format="color" />
        <attr name="csb_text_size" format="dimension" />
        <attr name="csb_text_space" format="dimension" />
        <attr name="csb_thumb" format="reference" />
        <attr name="csb_progress" format="integer" />
        <attr name="csb_track_color" format="color" />
        <attr name="csb_progress_track_color" format="color" />
        <attr name="csb_track_height" format="dimension" />
        <attr name="csb_track_offset" format="dimension"/>
        <attr name="csb_thumb_offset" format="dimension"/>
        <attr name="csb_text_potions">
            <enum name="top" value="1" />
            <enum name="bottom" value="2" />
        </attr>
    </declare-styleable>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值