垂直进度条VerticalSeekBar

来源:互联网 发布:seo百分百秒收录 编辑:程序博客网 时间:2024/04/29 11:55

水平的进度条见多了,总会想见个垂直的进度条开开眼。今天咱就试试。
要说原理也简单,就是把宽高倒置,其他的理论上都不需要动,发现问题再补补也就行了。

官方提供

官方是提供了垂直进度条的例子源码的,位置在android-sdk-windows\sources\android-23\com\android\example\rscamera\VerticalSeekBar.java,当然首先你SDK中要有Android 6.0。
VerticalSeekBar.java

/** * Class to create a vertical slider */public class VerticalSeekBar extends SeekBar {    public VerticalSeekBar(Context context) {        super(context);    }    public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public VerticalSeekBar(Context context, AttributeSet attrs) {        super(context, attrs);    }    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(h, w, oldh, oldw);    }    @Override    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(heightMeasureSpec, widthMeasureSpec);        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());    }    protected void onDraw(Canvas c) {        c.rotate(-90);        c.translate(-getHeight(), 0);        super.onDraw(c);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        if (!isEnabled()) {            return false;        }        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:            case MotionEvent.ACTION_MOVE:            case MotionEvent.ACTION_UP:                setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));                onSizeChanged(getWidth(), getHeight(), 0, 0);                break;            case MotionEvent.ACTION_CANCEL:                break;        }        return true;    }}

继承SeekBar是最简单快捷的,不用重写太多方法,只需要把
onMeasure
onSizeChanged
onDraw
三个方法作一些改动;但也有一些问题,比如只能响应onPregress方法,为了让他能响应onStartTrackingTouch和onStopTrackingTouch方法,只好再加一些代码,于是有了改进版。

稍作改进

VerticalSeekBar2.java

public class VerticalSeekBar2 extends SeekBar {    private Drawable mThumb;    private OnSeekBarChangeListener mOnSeekBarChangeListener;    public VerticalSeekBar2(Context context) {        super(context);    }    public VerticalSeekBar2(Context context, AttributeSet attrs) {        super(context, attrs);    }    public VerticalSeekBar2(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {        mOnSeekBarChangeListener = l;    }    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(h, w, oldh, oldw);    }    @Override    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(heightMeasureSpec, widthMeasureSpec);        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());    }    protected void onDraw(Canvas c) {        c.rotate(-90);        c.translate(-getHeight(), 0);        super.onDraw(c);    }    void onProgressRefresh(float scale, boolean fromUser) {        Drawable thumb = mThumb;        if (thumb != null) {            setThumbPos(getHeight(), thumb, scale, Integer.MIN_VALUE);            invalidate();        }        if (mOnSeekBarChangeListener != null) {            mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);        }    }    private void setThumbPos(int w, Drawable thumb, float scale, int gap) {        int available = w - getPaddingLeft() - getPaddingRight();        int thumbWidth = thumb.getIntrinsicWidth();        int thumbHeight = thumb.getIntrinsicHeight();        int thumbPos = (int) (scale * available + 0.5f);        // int topBound = getWidth() / 2 - thumbHeight / 2 - getPaddingTop();        // int bottomBound = getWidth() / 2 + thumbHeight / 2 - getPaddingTop();        int topBound, bottomBound;        if (gap == Integer.MIN_VALUE) {            Rect oldBounds = thumb.getBounds();            topBound = oldBounds.top;            bottomBound = oldBounds.bottom;        } else {            topBound = gap;            bottomBound = gap + thumbHeight;        }        thumb.setBounds(thumbPos, topBound, thumbPos + thumbWidth, bottomBound);    }    public void setThumb(Drawable thumb) {        mThumb = thumb;        super.setThumb(thumb);    }    void onStartTrackingTouch() {        if (mOnSeekBarChangeListener != null) {            mOnSeekBarChangeListener.onStartTrackingTouch(this);        }    }    void onStopTrackingTouch() {        if (mOnSeekBarChangeListener != null) {            mOnSeekBarChangeListener.onStopTrackingTouch(this);        }    }    private void attemptClaimDrag() {        if (getParent() != null) {            getParent().requestDisallowInterceptTouchEvent(true);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        if (!isEnabled()) {            return false;        }        switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            setPressed(true);            onStartTrackingTouch();            break;        case MotionEvent.ACTION_MOVE:            attemptClaimDrag();            setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));            break;        case MotionEvent.ACTION_UP:            onStopTrackingTouch();            setPressed(false);            break;        case MotionEvent.ACTION_CANCEL:            onStopTrackingTouch();            setPressed(false);            break;        }        return true;    }

为了响应另外两个不知道怎么就被onPregress抛弃的方法,添了这么多代码真是罪过,不过都是从SeekBar的父类AbsSeekBar中仿写过来的,逻辑稍作改动就能用。

对比测试

上图。
测试用图
左边是官方例子中的,右边是改进过的。
请自行测试~~
测试源码

0 0
原创粉丝点击