标签:
自定义实现了一个选定范围值的控件,刻度尺为等分的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; }
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://blog.csdn.net/huweigoodboy/article/details/44286307