RangeSeekBarView 选定范围值的控件

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

实现效果:

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

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

@Overrideprotected 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。

@Overrideprotected 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; //计算一份所占的宽度 一定要用floatmThumbLeft.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;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth=getMeasuredWidth();}@Overrideprotected 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);}@Overridepublic 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);}}

下载地址

力微休负重,言轻莫劝人。

RangeSeekBarView 选定范围值的控件

相关文章:

你感兴趣的文章:

标签云: