Custom view’s custom sliding seekbar

Searching for custom seekbars is all based on the native seekbar. You need to drag the slider, and click on a certain position of the seekbar to jump there. What I want is to adjust it by sliding it like the brightness bar of miui10. Since there is no such Just do it yourself.

First of all, you have to know what you want to draw. Here is the rendering:

Implementation ideas: 

The main thing is to draw two original rectangles, a background and a progress box, and then trigger the sliding to change the progress through onTouchEvent.

First declare two pens, one for background and one for progress, and then set the color for the pens:

private Paint bgPaint;
private Paint barPaint;
public void init(){
        bgPaint = new Paint();
        barPaint = new Paint();
        bgPaint.setAntiAlias(true);
        barPaint.setAntiAlias(true);
        bgPaint.setColor(Color.GRAY);
        barPaint.setColor(Color.WHITE);
    }

Draw the Kangkang effect in the drawing method, and you can see that you are already half successful:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        canvas.drawRoundRect(0,0,width,height,10,10,bgPaint);
        canvas.drawRoundRect(0,0,width/2f,height,10,10,barPaint);
    }

 

 The next step is to set it to be dynamic and accept changes in the progress value to modify the progress, which is the width of the second rounded rectangle above:

    private int maxProgress = 100;
    private int currentProgress = 50;
    private float radius = 10;
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        canvas.drawRoundRect(0f,0f,width,height,radius,radius,bgPaint);
        float barWidth = width*1.0f/ maxProgress * currentProgress;
        canvas.drawRoundRect(0,0,barWidth,height,radius,radius,barPaint);
    }

The current progress, maximum progress, and corner radius can be modified dynamically later.

Then, we handle the touch event.

The idea is to record the current progress and the x-axis value of the currently pressed point when pressing, and then calculate the sliding distance when sliding. Use the sliding distance ÷ control width = sliding progress ÷ maximum progress to get the sliding progress, and then Use the recorded current progress + sliding progress to assign the current progress, and then redraw it and it will be ok:

    private float downX;
    private int currentCountTemp;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                currentCountTemp = currentProgress;
                return true;
            case MotionEvent.ACTION_MOVE:
                float downXTemp = event.getX();
                float x = downXTemp - downX;
                currentProgress = currentCountTemp + (int) (x/getWidth() * maxProgress);
                if(currentProgress < 0){
                    currentProgress = 0;
                }else if(currentProgress > maxProgress){
                    currentProgress = maxProgress;
                }
                invalidate();
                return true;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

Finally, release all the code. I am too lazy to declare the xml attribute. You can do it yourself:

public class MySeekBar extends View {

    private String TAG = "MySeekBar";
    private int maxProgress = 100;
    private int currentProgress = 50;
    private float radius = 10;

    private Paint bgPaint;
    private Paint barPaint;

    public void setBgColor(int bgColor) {
        bgPaint.setColor(bgColor);
    }

    public void setBarColor(int barColor) {
        barPaint.setColor(barColor);
    }

    public int getMaxProgress() {
        return maxProgress;
    }

    public void setMaxProgress(int maxProgress) {
        this.maxProgress = maxProgress;
    }

    public int getCurrentProgress() {
        return currentProgress;
    }

    public void setCurrentProgress(int currentProgress) {
        this.currentProgress = currentProgress;
    }

    public void setRadius(float radius) {
        this.radius = radius;
    }

    public MySeekBar(Context context) {
        super(context);
        init();
    }

    public MySeekBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

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

    public void init(){
        bgPaint = new Paint();
        barPaint = new Paint();
        bgPaint.setAntiAlias(true);
        barPaint.setAntiAlias(true);
        bgPaint.setColor(Color.GRAY);
        barPaint.setColor(Color.WHITE);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        canvas.drawRoundRect(0f,0f,width,height,radius,radius,bgPaint);
        float barWidth = width*1.0f/ maxProgress * currentProgress;
        canvas.drawRoundRect(0,0,barWidth,height,radius,radius,barPaint);
    }

    private float downX;
    private int currentCountTemp;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                currentCountTemp = currentProgress;
                Log.i(TAG, "onTouchEvent: downX:"+downX);
                return true;
            case MotionEvent.ACTION_MOVE:
                float downXTemp = event.getX();
                float x = downXTemp - downX;
                currentProgress = currentCountTemp + (int) (x/getWidth() * maxProgress);
                if(currentProgress < 0){
                    currentProgress = 0;
                }else if(currentProgress > maxProgress){
                    currentProgress = maxProgress;
                }
                invalidate();
                if(onDragListener != null){
                    onDragListener.onProgressChange(currentProgress);
                }
                return true;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    public interface OnDragListener{
        void onProgressChange(int progress);
    }
    private OnDragListener onDragListener;
    public void setOnDragListener(OnDragListener onDragListener) {
        this.onDragListener = onDragListener;
    }
}

Guess you like

Origin blog.csdn.net/qq_35584878/article/details/119893357