标签:
自定义实现了一个选定范围值的控件,刻度尺为等分的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