Android RangeSeekBarView 选定范围值的控件
自定义实现了一个选定范围值的控件,刻度尺为等分的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);
- }
- 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);
- }
- }
- /**
- * 画 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);
- }
- }
下载地址 http://download.****.net/detail/huweigoodboy/8508243