码迷,mamicode.com
首页 > 其他好文 > 详细

RangeSeekBarView 选定范围值的控件

时间:2015-03-17 14:19:10      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:

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


下载地址


RangeSeekBarView 选定范围值的控件

标签:

原文地址:http://blog.csdn.net/huweigoodboy/article/details/44286307

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!