RangeSeekBarView 选定范围值的控件

来源:互联网 发布:windows介质创建工具 编辑:程序博客网 时间:2024/05/04 19:43

自定义实现了一个选定范围值的控件,刻度尺为等分的100等分。模仿二手车app中筛选选定区间的控件。


实现效果:


首先将这个控件分成四部分,位置标记,刻度,尺子,游标。



一,测量子控件的尺度,继承onMeasure().由子空间的尺寸来确定控件的尺寸。

    @Override    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        measureChildren(widthMeasureSpec,heightMeasureSpec);    //测量子控件        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int mWidth=MeasureSpec.getSize(widthMeasureSpec);        proPaddingLeftAndRight=mThumbLeft.getMeasuredWidth()/2;        mLeftLimit=proPaddingLeftAndRight;        mRightLimit=mWidth-proPaddingLeftAndRight;        //位置标记的高度+尺子的刻度高度+尺子的高度+游标的高度        setMeasuredDimension(mWidth,mThumbPlaceHeight+RULE_HEIGHT_PX+mProgressBarHeight+mThumbLeft.getMeasuredHeight());    }

二,对控件进行布局。

由于游标需要去监听他的滑动事件,所以这里自定义一个游标控件ThumbView。

@Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        int heightSum=0;        heightSum+=mThumbPlaceHeight;        heightSum+=RULE_HEIGHT_PX;        heightSum+=mProgressBarHeight;        mPartWidth=(mRightLimit-mLeftLimit)/(float)mMaxValue;   //计算一份所占的宽度  一定要用float        mThumbLeft.setLimit(mLeftLimit,mRightLimit);    //设置可以移动的范围        mThumbLeft.layout(0,heightSum,mThumbLeft.getMeasuredWidth(),b-10);      //设置在父布局的位置        mThumbRight.setLimit(mLeftLimit,mRightLimit);        mThumbRight.layout(0,heightSum,mThumbLeft.getMeasuredWidth(),b-10);        onLayoutPrepared();     //layout调用后调用的方法,比如设置thumb limit    }

三,绘制尺子,尺子的刻度,尺子上的位置标记控件。

绘制尺子,其中mProBaseline为尺子top的位置。尺子的range实际是两个不同的矩形框。

 /**     * 画尺子     *@param canvas     */    protected void drawProgressBar(Canvas canvas){        //画背景        Paint paint=new Paint();        paint.setAntiAlias(true);        paint.setColor(getResources().getColor(R.color.grey));        Rect rect=new Rect(mLeftLimit,mProBaseline,mRightLimit,mProBaseline+mProgressBarHeight);        canvas.drawRect(rect,paint);        //画进度        paint.setColor(getResources().getColor(R.color.blue));        rect=new Rect(mThumbLeft.getCenterX(),mProBaseline,mThumbRight.getCenterX(),mProBaseline+mProgressBarHeight);        canvas.drawRect(rect,paint);    }
绘制刻度,这里将尺子分成了100等分,然后前5份和后5份不画,中间部分每两份画一条线,每10份画一条长线。

    protected void drawRule(Canvas canvas){        Paint paint=new Paint();        paint.setStrokeWidth(1);        paint.setColor(getResources().getColor(R.color.grey));        paint.setTextSize(20);        paint.setTextAlign(Paint.Align.CENTER);        paint.setAntiAlias(true);        //一次遍历两份,绘制的位置都是在奇数位置        for(int i=5;i<=mMaxValue;i+=2){            if(i<PART_ITEM||i>mMaxValue-PART_ITEM){                continue;            }            float degX=mLeftLimit+i*mPartWidth;            int degY;            if((i-PART_ITEM)%(PART_ITEM*2)==0){                degY=mProBaseline-DensityUtil.dip2px(getContext(),LONGLINE_HEIGHT);                canvas.drawText(degs[(i-5)/10]+unitStr,degX,degY,paint);    //画文字            }else{                degY=mProBaseline-DensityUtil.dip2px(getContext(),SHORTLINE_HEIGHT);            }            canvas.drawLine(degX,mProBaseline,degX,degY,paint);        }    }
绘制标记控件,根据游标ThumbView的isMoving属性来判断是否需要绘制标记数值。isMoving true绘制,false 不 绘制

    /**     * 画 Thumb 位置的数值(标记)     */    protected void drawRodPlaceValue(Canvas canvas,ThumbView thumbView){        int centerX=thumbView.getCenterX();        Paint paint=new Paint();        BitmapDrawable bd= (BitmapDrawable) mThumbPlaceDrawable;        canvas.drawBitmap(bd.getBitmap(),centerX-mThumbPlaceDrawable.getIntrinsicWidth()/2,0,paint);        paint.setColor(Color.WHITE);        paint.setTextAlign(Paint.Align.CENTER);        paint.setTextSize(30);        canvas.drawText(geneareThumbValue(thumbView)+"",centerX,mThumbDrawable.getIntrinsicHeight()/2,paint);    }

四,相关计算

要根据游标在刻度尺上的位置,计算进度。


    private int geneareThumbValue(ThumbView view){        //todo 这里只是计算了100之多少的值,需要自行转换成刻度上的值        int proValue=mMaxValue*(view.getCenterX()-mLeftLimit)/(mRightLimit-mLeftLimit);        return proValue;    }

五,游标控件 ThumbView

1,mLeftLimit, mRightLimit是游标能浮动的位置。

2,当Touch事件为move时,来改变自身的位置。

package com.jayce.uidefine;import android.content.Context;import android.graphics.Rect;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.ImageView;/** * @author jayce * @date 2015/3/12 */public class ThumbView extends ImageView {    private RangeSeekBar rangeSeekBar;    private int mDownX=0;    private int mWidth;    private int mLeftLimit=0;    private int mRightLimit=Integer.MAX_VALUE;    private Rect rect;    private int mCenterX;   //游标的中心位置    private boolean mIsMoving;      //游标是否正在移动    private OnThumbListener listener;    public ThumbView(Context context) {        this(context, null);    }    public ThumbView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public ThumbView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    public void setRangeSeekBar(RangeSeekBar rangeSeekBar) {        this.rangeSeekBar = rangeSeekBar;    }    public void setLimit(int mLeftLimit,int mRightLimit) {        this.mLeftLimit = mLeftLimit;        this.mRightLimit=mRightLimit;    }    public int getCenterX() {        return mCenterX;    }    /**     * 设置中心位置,不超过左右的limit,就刷新整个控件,并且回调onThumbChange()     * @param centerX     */    public void setCenterX(int centerX) {        int left=centerX-mWidth/2,right=centerX+mWidth/2;        if(centerX<mLeftLimit) {            left=mLeftLimit-mWidth/2;            right=mLeftLimit+mWidth/2;        }        if(centerX>mRightLimit){            left=mRightLimit-mWidth/2;            right=mRightLimit+mWidth/2;        }        this.mCenterX = (left+right)/2;        if(left!=rect.left||right!=rect.right){            rect.union(left,rect.top,right,rect.bottom);            layout(left, rect.top, right, rect.bottom);            //invalidate(rect);            rangeSeekBar.invalidate();            if(listener!=null){                listener.onThumbChange(100*((left+right)/2-mLeftLimit)/(mRightLimit-mLeftLimit));            }        }    }    public boolean isMoving() {        return mIsMoving;    }    public void setOnThumbListener(OnThumbListener listener) {        this.listener = listener;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        mWidth=getMeasuredWidth();    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        rect=new Rect(left,top,right,bottom);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                mDownX = (int) event.getX();                mIsMoving=false;                break;            case MotionEvent.ACTION_MOVE:                int nowX = (int) event.getX();                int left = rect.left + nowX - mDownX;                int right = rect.right + nowX - mDownX;                mIsMoving=true;                setCenterX((left+right)/2);                break;            case MotionEvent.ACTION_UP:                mIsMoving=false;                rangeSeekBar.invalidate();                break;        }        return true;    }    public interface OnThumbListener{        public void onThumbChange(int i);    }}


下载地址


1 0