custom made arc shaped seekbar

筅森魡賤 提交于 2019-12-04 12:09:19

Drawing a ProgressBar with any shape, is pretty easy. With the SeekBar you have some complexity, since you have to achieve 3 diferent things:

  1. Draw the line
  2. Draw the draggable thumb, if you want.
  3. Handle the user interaction

You have to think of it as an arc that is draw inside a rectangle. So point 3 could be easy: just let the user move the finger in a horizontal line, or exactly over the arc, but considering only the x coordinate of the touch event. What does this mean, in short? ok, good news: you dont have to do anything, since thats the normal behavior of the base SeekBar.

For the second point, you can choose an image for the handler, and write it in the corresponding position with a little maths. Or you can forget the handler for know, and just draw the seek bar as a line representing the full track, and another line over it representing the progress. When you have this working, if you want you can add the handler.

And for the first point, this is the main one, but its not hard to achieve. You can use this code:

UPDATE: I made some improvements in the code

public class ArcSeekBar extends SeekBar {


    public ArcSeekBar(Context context, AttributeSet attrs) {
            super(context, attrs);

    }

    public ArcSeekBar(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);

    }

    private Paint mBasePaint;
    private Paint mProgressPaint;
    private RectF mOval = new RectF(5, 5, 550, 550);
    private int defaultmax = 180;
    private int startAngle=180;
    private int strokeWidth=10;

    private int trackColor=0xFF000000;
    private int progressColor=0xFFFF0000;



    public void setOval(RectF mOval) {
            this.mOval = mOval;
    }



    public void setStartAngle(int startAngle) {
            this.startAngle = startAngle;
    }

    public void setStrokeWidth(int strokeWidth) {
            this.strokeWidth = strokeWidth;
    }

    public void setTrackColor(int trackColor) {
            this.trackColor = trackColor;
    }

    public void setProgressColor(int progressColor) {
            this.progressColor = progressColor;
    }

    public ArcSeekBar(Context context) {
            super(context);
            mBasePaint = new Paint();
            mBasePaint.setAntiAlias(true);
            mBasePaint.setColor(trackColor);
            mBasePaint.setStrokeWidth(strokeWidth);
            mBasePaint.setStyle(Paint.Style.STROKE);

            mProgressPaint = new Paint();
            mProgressPaint.setAntiAlias(true);
            mProgressPaint.setColor(progressColor);
            mProgressPaint.setStrokeWidth(strokeWidth);
            mProgressPaint.setStyle(Paint.Style.STROKE);

            setMax(defaultmax);// degrees


    }

    @Override
    protected void onDraw(Canvas canvas) {
            canvas.drawArc(mOval, startAngle, getMax(), false, mBasePaint);
            canvas.drawArc(mOval, startAngle, getProgress(), false, mProgressPaint);
            invalidate();
            //Log.i("ARC", getProgress()+"/"+getMax());

    }

 }

Of course, you can and you should make everything configurable, be means of the contructor, or with some setters for the start and end angles, dimensions of the containing rectangle, stroke widths, colors, etc.

Also, note that the arc is drawn from 0 to getProgress, being this number an angle relative to the x axis, growing clocwise, so, if it go from 0 to 90 degrees, it will be something like:

Of course you can change this: canvas.drawArc get any number as an angle, and it is NOT treated as module 360, but you can do the maths and have it starting and ending in any point you want.

In my example the beggining is in the 9 of a clock, and it takes 180 degrees, to the 3 in the clock.

UPDATE

I uploaded a running example to github

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!