美文网首页
Android正负Seekbar

Android正负Seekbar

作者: 不会弹钢琴de大叔 | 来源:发表于2023-08-08 08:37 被阅读0次

项目需要做了一个正负滑动的Seekbar

public class CenterSeekBarView extends View {
    private static final String TAG = CenterSeekBarView.class.getSimpleName();
    private Paint mThumbPaint;
    private Paint mProgressPaint;
    private Paint mTextPaint;
    private Paint mThumbTextPaint;
    @ColorInt
    private int progressBackColor;
    @ColorInt
    private int progressColor;
    private int maxValue;
    private int minValue;
    private int measuredWidth;
    private int measuredHeight;
    private float thumbRadius;
    private int progressBarCoarse;
    private int viewPadding;
    private final float[] thumbPosition = new float[2];
    private float lastX;
    private float lastY;
    private boolean canMove;

    public CenterSeekBarView(Context context) {
        this(context, null);
        init();
    }

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

    public CenterSeekBarView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mThumbPaint = new Paint();
        mThumbPaint.setAntiAlias(true);
        mThumbPaint.setStyle(Paint.Style.FILL);
        mThumbPaint.setColor(Color.parseColor("#303030"));
        mProgressPaint = new Paint();
        mProgressPaint.setAntiAlias(true);
        mProgressPaint.setStyle(Paint.Style.FILL);
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setColor(Color.parseColor("#FFFFFF"));
        mThumbTextPaint = new Paint();
        mThumbTextPaint.setAntiAlias(true);
        mThumbTextPaint.setStyle(Paint.Style.FILL);
        mThumbTextPaint.setColor(Color.parseColor("#FFFFFF"));

        progressBackColor = Color.parseColor("#C2C2C2");
        progressColor = Color.parseColor("#C79C5B");
        thumbRadius = dip2px(20);
        progressBarCoarse = dip2px(10);
        viewPadding = dip2px(40);
        maxValue = 10;
        minValue = -10;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        measuredWidth = getMeasuredWidth();
        measuredHeight = getMeasuredHeight();
        float x = measuredWidth / 2f;
        float y = measuredHeight / 2f;
        thumbPosition[0] = x;
        thumbPosition[1] = y;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawProgressBackground(canvas);
        drawProgressBar(canvas);
        drawThumb(canvas);
        drawText(canvas);
    }

    private void drawProgressBar(Canvas canvas) {
        float left = measuredWidth / 2f;
        float top = measuredHeight / 2f - progressBarCoarse / 2f;
        float right = thumbPosition[0];
        float bottom = measuredHeight / 2f + progressBarCoarse / 2f;
        mProgressPaint.setColor(progressColor);
        canvas.drawRoundRect(left, top, right, bottom, 5, 5, mProgressPaint);
    }

    private void drawProgressBackground(Canvas canvas) {
        float left = viewPadding;
        float top = measuredHeight / 2f - progressBarCoarse / 2f;
        float right = measuredWidth - viewPadding;
        float bottom = measuredHeight / 2f + progressBarCoarse / 2f;
        mProgressPaint.setColor(progressBackColor);
        canvas.drawRoundRect(left, top, right, bottom, 5, 5, mProgressPaint);
    }

    private void drawThumb(Canvas canvas) {
        canvas.drawCircle(thumbPosition[0], thumbPosition[1], thumbRadius, mThumbPaint);
        mThumbTextPaint.setTextAlign(Paint.Align.CENTER);
        canvas.drawText(getPercent(), thumbPosition[0], thumbPosition[1] - thumbRadius - dip2px(10), mThumbTextPaint);
    }

    private void drawText(Canvas canvas) {
        float y = measuredHeight / 2f + progressBarCoarse / 2f + dip2px(20);
        mTextPaint.setTextAlign(Paint.Align.LEFT);
        canvas.drawText(minValue + "km/h", viewPadding, y, mTextPaint);
        mTextPaint.setTextAlign(Paint.Align.RIGHT);
        canvas.drawText(maxValue + "km/h", measuredWidth - viewPadding, y, mTextPaint);
    }

    private String getPercent() {
        float total = measuredWidth / 2f - viewPadding;
        float current = Math.abs(thumbPosition[0] - measuredWidth / 2f);
        float percent = current / total;
        Log.d(TAG, "getPercent: " + total + "," + current + "<" + percent);
        if (thumbPosition[0] < measuredWidth / 2f) {
            return "" + (int) (percent * minValue);
        }
        return (int) (percent * maxValue) + "";
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            Log.d(TAG, "onTouchEvent: enable false");
            return false;
        }
        int x = (int) event.getRawX();
        int y = (int) event.getRawY();
        float px = event.getX();
        float py = event.getY();
        int dealtX = 0;
        int dealtY = 0;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);
                canMove = checkInThumb(px, py);
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "onTouchEvent: move");
                dealtX += Math.abs(x - lastX);
                dealtY += Math.abs(y - lastY);
                // 这里是拦截判断依据是左右上下滑动,水平进行滑动,自己消费,请求父类ViewPage不拦截;竖直方向滑动,交给父类Scrollview
                getParent().requestDisallowInterceptTouchEvent(dealtX >= dealtY);
                lastX = x;
                lastY = y;
                setMovePosition(px);
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "onTouchEvent: up");
                canMove = false;
                setMovePosition(px);
                getParent().requestDisallowInterceptTouchEvent(false);
                break;
            default:
                break;
        }
        return true;
    }

    private void setMovePosition(float px) {
        if (px > measuredWidth - viewPadding) {
            px = measuredWidth - viewPadding;
        } else if (px < viewPadding) {
            px = viewPadding;
        }
//        float tempX = checkIntPosition(px);
//        if (tempX > measuredWidth - viewPadding) {
//            tempX = measuredWidth - viewPadding;
//        } else if (tempX < viewPadding) {
//            tempX = viewPadding;
//        }
        thumbPosition[0] = px;
        postInvalidate();
    }

    private float checkIntPosition(float x) {
        float total = measuredWidth / 2f - viewPadding;
        float current = Math.abs(x - measuredWidth / 2f);
        float percent = current / total;
        boolean isLeft = x < measuredWidth / 2f;
        if (isLeft) {
            float flMin = percent * minValue;
            BigDecimal bigDecimal = new BigDecimal(flMin);
            bigDecimal = bigDecimal.setScale(1, RoundingMode.HALF_UP);
            float px = bigDecimal.floatValue() / minValue * measuredWidth / 2f;
            return measuredWidth / 2f - px;
        } else {
            float flMax = percent * maxValue;
            BigDecimal bigDecimal = new BigDecimal(flMax);
            bigDecimal = bigDecimal.setScale(1, RoundingMode.HALF_UP);
            float px = bigDecimal.floatValue() / maxValue * (measuredWidth / 2f);
            return px + measuredWidth / 2f;
        }
    }

    public void setMaxValue(int maxValue) {
        this.maxValue = maxValue;
    }

    public void setMinValue(int minValue) {
        this.minValue = minValue;
    }

    public void setThumbRadius(int thumbRadius) {
        this.thumbRadius = thumbRadius;
    }

    private boolean checkInThumb(float x, float y) {
        return checkPosition(thumbPosition[0], thumbPosition[1], thumbRadius * 2, x, y);
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    private int dip2px(float dpValue) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     */
    private int px2dip(float pxValue) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    public void setEnable(boolean enable) {
        setEnabled(enable);
    }

    /**
     * 判断坐标是否在指定范围内
     *
     * @param targetX 目标x
     * @param targetY 目标y
     * @param size    尺寸
     * @param x       x
     * @param y       y
     * @return
     */
    private boolean checkPosition(float targetX, float targetY, float size, float x, float y) {
        float distanceX = Math.abs(targetX + size / 2 - x);
        float distanceY = Math.abs(targetY + size / 2 - y);
        double distanceZ = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2));
        return distanceZ < size / 2;
    }

    /**
     * 判断浮点类型数据是不是整数,整数去除小数点
     *
     * @param d double类型数据
     * @return string数据
     */
    public static String doubleTrans(float d) {
        if (Math.round(d) - d == 0) {
            return String.valueOf((long) d);
        }
        return String.valueOf(d);
    }

相关文章

网友评论

      本文标题:Android正负Seekbar

      本文链接:https://www.haomeiwen.com/subject/qzygpdtx.html