Android RangeSeekBarView 选定范围值的控件

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


实现效果:


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



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

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  3.     measureChildren(widthMeasureSpec,heightMeasureSpec);    //测量子控件  
  4.     super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  5.   
  6.     int mWidth=MeasureSpec.getSize(widthMeasureSpec);  
  7.     proPaddingLeftAndRight=mThumbLeft.getMeasuredWidth()/2;  
  8.     mLeftLimit=proPaddingLeftAndRight;  
  9.     mRightLimit=mWidth-proPaddingLeftAndRight;  
  10.   
  11.     //位置标记的高度+尺子的刻度高度+尺子的高度+游标的高度  
  12.     setMeasuredDimension(mWidth,mThumbPlaceHeight+RULE_HEIGHT_PX+mProgressBarHeight+mThumbLeft.getMeasuredHeight());  
  13. }  

二,对控件进行布局。

由于游标需要去监听他的滑动事件,所以这里自定义一个游标控件ThumbView。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  3.         int heightSum=0;  
  4.   
  5.         heightSum+=mThumbPlaceHeight;  
  6.   
  7.         heightSum+=RULE_HEIGHT_PX;  
  8.   
  9.         heightSum+=mProgressBarHeight;  
  10.   
  11.         mPartWidth=(mRightLimit-mLeftLimit)/(float)mMaxValue;   //计算一份所占的宽度  一定要用float  
  12.   
  13.         mThumbLeft.setLimit(mLeftLimit,mRightLimit);    //设置可以移动的范围  
  14.         mThumbLeft.layout(0,heightSum,mThumbLeft.getMeasuredWidth(),b-10);      //设置在父布局的位置  
  15.   
  16.         mThumbRight.setLimit(mLeftLimit,mRightLimit);  
  17.         mThumbRight.layout(0,heightSum,mThumbLeft.getMeasuredWidth(),b-10);  
  18.   
  19.         onLayoutPrepared();     //layout调用后调用的方法,比如设置thumb limit  
  20.     }  

三,绘制尺子,尺子的刻度,尺子上的位置标记控件。

绘制尺子,其中mProBaseline为尺子top的位置。尺子的range实际是两个不同的矩形框。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.     * 画尺子 
  3.     *@param canvas 
  4.     */  
  5.    protected void drawProgressBar(Canvas canvas){  
  6.        //画背景  
  7.        Paint paint=new Paint();  
  8.        paint.setAntiAlias(true);  
  9.        paint.setColor(getResources().getColor(R.color.grey));  
  10.        Rect rect=new Rect(mLeftLimit,mProBaseline,mRightLimit,mProBaseline+mProgressBarHeight);  
  11.        canvas.drawRect(rect,paint);  
  12.   
  13.        //画进度  
  14.        paint.setColor(getResources().getColor(R.color.blue));  
  15.        rect=new Rect(mThumbLeft.getCenterX(),mProBaseline,mThumbRight.getCenterX(),mProBaseline+mProgressBarHeight);  
  16.        canvas.drawRect(rect,paint);  
  17.    }  
绘制刻度,这里将尺子分成了100等分,然后前5份和后5份不画,中间部分每两份画一条线,每10份画一条长线。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. protected void drawRule(Canvas canvas){  
  2.     Paint paint=new Paint();  
  3.     paint.setStrokeWidth(1);  
  4.     paint.setColor(getResources().getColor(R.color.grey));  
  5.     paint.setTextSize(20);  
  6.     paint.setTextAlign(Paint.Align.CENTER);  
  7.     paint.setAntiAlias(true);  
  8.   
  9.     //一次遍历两份,绘制的位置都是在奇数位置  
  10.     for(int i=5;i<=mMaxValue;i+=2){  
  11.         if(i<PART_ITEM||i>mMaxValue-PART_ITEM){  
  12.             continue;  
  13.         }  
  14.   
  15.   
  16.         float degX=mLeftLimit+i*mPartWidth;  
  17.         int degY;  
  18.   
  19.         if((i-PART_ITEM)%(PART_ITEM*2)==0){  
  20.             degY=mProBaseline-DensityUtil.dip2px(getContext(),LONGLINE_HEIGHT);  
  21.             canvas.drawText(degs[(i-5)/10]+unitStr,degX,degY,paint);    //画文字  
  22.         }else{  
  23.             degY=mProBaseline-DensityUtil.dip2px(getContext(),SHORTLINE_HEIGHT);  
  24.         }  
  25.         canvas.drawLine(degX,mProBaseline,degX,degY,paint);  
  26.     }  
  27. }  
绘制标记控件,根据游标ThumbView的isMoving属性来判断是否需要绘制标记数值。isMoving true绘制,false 不 绘制

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 画 Thumb 位置的数值(标记) 
  3.  */  
  4. protected void drawRodPlaceValue(Canvas canvas,ThumbView thumbView){  
  5.     int centerX=thumbView.getCenterX();  
  6.     Paint paint=new Paint();  
  7.     BitmapDrawable bd= (BitmapDrawable) mThumbPlaceDrawable;  
  8.     canvas.drawBitmap(bd.getBitmap(),centerX-mThumbPlaceDrawable.getIntrinsicWidth()/2,0,paint);  
  9.   
  10.     paint.setColor(Color.WHITE);  
  11.     paint.setTextAlign(Paint.Align.CENTER);  
  12.     paint.setTextSize(30);  
  13.     canvas.drawText(geneareThumbValue(thumbView)+"",centerX,mThumbDrawable.getIntrinsicHeight()/2,paint);  
  14. }  

四,相关计算

要根据游标在刻度尺上的位置,计算进度。


[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private int geneareThumbValue(ThumbView view){  
  2.     //todo 这里只是计算了100之多少的值,需要自行转换成刻度上的值  
  3.     int proValue=mMaxValue*(view.getCenterX()-mLeftLimit)/(mRightLimit-mLeftLimit);  
  4.     return proValue;  
  5. }  

五,游标控件 ThumbView

1,mLeftLimit, mRightLimit是游标能浮动的位置。

2,当Touch事件为move时,来改变自身的位置。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.jayce.uidefine;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Rect;  
  5. import android.util.AttributeSet;  
  6. import android.view.MotionEvent;  
  7. import android.widget.ImageView;  
  8.   
  9. /** 
  10.  * @author jayce 
  11.  * @date 2015/3/12 
  12.  */  
  13. public class ThumbView extends ImageView {  
  14.   
  15.     private RangeSeekBar rangeSeekBar;  
  16.   
  17.     private int mDownX=0;  
  18.     private int mWidth;  
  19.   
  20.     private int mLeftLimit=0;  
  21.     private int mRightLimit=Integer.MAX_VALUE;  
  22.   
  23.     private Rect rect;  
  24.   
  25.     private int mCenterX;   //游标的中心位置  
  26.   
  27.     private boolean mIsMoving;      //游标是否正在移动  
  28.   
  29.     private OnThumbListener listener;  
  30.   
  31.     public ThumbView(Context context) {  
  32.         this(context, null);  
  33.     }  
  34.   
  35.     public ThumbView(Context context, AttributeSet attrs) {  
  36.         this(context, attrs, 0);  
  37.     }  
  38.   
  39.     public ThumbView(Context context, AttributeSet attrs, int defStyleAttr) {  
  40.         super(context, attrs, defStyleAttr);  
  41.     }  
  42.   
  43.     public void setRangeSeekBar(RangeSeekBar rangeSeekBar) {  
  44.         this.rangeSeekBar = rangeSeekBar;  
  45.     }  
  46.   
  47.     public void setLimit(int mLeftLimit,int mRightLimit) {  
  48.         this.mLeftLimit = mLeftLimit;  
  49.         this.mRightLimit=mRightLimit;  
  50.     }  
  51.   
  52.     public int getCenterX() {  
  53.         return mCenterX;  
  54.     }  
  55.   
  56.     /** 
  57.      * 设置中心位置,不超过左右的limit,就刷新整个控件,并且回调onThumbChange() 
  58.      * @param centerX 
  59.      */  
  60.     public void setCenterX(int centerX) {  
  61.         int left=centerX-mWidth/2,right=centerX+mWidth/2;  
  62.         if(centerX<mLeftLimit) {  
  63.             left=mLeftLimit-mWidth/2;  
  64.             right=mLeftLimit+mWidth/2;  
  65.         }  
  66.   
  67.         if(centerX>mRightLimit){  
  68.             left=mRightLimit-mWidth/2;  
  69.             right=mRightLimit+mWidth/2;  
  70.         }  
  71.   
  72.         this.mCenterX = (left+right)/2;  
  73.   
  74.         if(left!=rect.left||right!=rect.right){  
  75.             rect.union(left,rect.top,right,rect.bottom);  
  76.             layout(left, rect.top, right, rect.bottom);  
  77.             //invalidate(rect);  
  78.             rangeSeekBar.invalidate();  
  79.   
  80.             if(listener!=null){  
  81.                 listener.onThumbChange(100*((left+right)/2-mLeftLimit)/(mRightLimit-mLeftLimit));  
  82.             }  
  83.         }  
  84.     }  
  85.   
  86.     public boolean isMoving() {  
  87.         return mIsMoving;  
  88.     }  
  89.   
  90.     public void setOnThumbListener(OnThumbListener listener) {  
  91.         this.listener = listener;  
  92.     }  
  93.   
  94.     @Override  
  95.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  96.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  97.   
  98.         mWidth=getMeasuredWidth();  
  99.     }  
  100.   
  101.     @Override  
  102.     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {  
  103.         super.onLayout(changed, left, top, right, bottom);  
  104.   
  105.         rect=new Rect(left,top,right,bottom);  
  106.     }  
  107.   
  108.     @Override  
  109.     public boolean onTouchEvent(MotionEvent event) {  
  110.         switch (event.getAction()) {  
  111.             case MotionEvent.ACTION_DOWN:  
  112.                 mDownX = (int) event.getX();  
  113.                 mIsMoving=false;  
  114.   
  115.                 break;  
  116.             case MotionEvent.ACTION_MOVE:  
  117.                 int nowX = (int) event.getX();  
  118.   
  119.                 int left = rect.left + nowX - mDownX;  
  120.                 int right = rect.right + nowX - mDownX;  
  121.                 mIsMoving=true;  
  122.                 setCenterX((left+right)/2);  
  123.                 break;  
  124.             case MotionEvent.ACTION_UP:  
  125.                 mIsMoving=false;  
  126.                 rangeSeekBar.invalidate();  
  127.                 break;  
  128.         }  
  129.         return true;  
  130.     }  
  131.   
  132.     public interface OnThumbListener{  
  133.         public void onThumbChange(int i);  
  134.     }  
  135. }  


下载地址 http://download.csdn.net/detail/huweigoodboy/8508243


使用中的问题:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:orientation="vertical">

    </LinearLayout>

    <com.jayce.uidefine.RangeSeekBar
        style="@style/progress_horizontal_my"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />


</LinearLayout>


这样的布局会出现底部剪头不显示的问题,如下即可解决:


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:orientation="vertical">
        <com.jayce.uidefine.RangeSeekBar
            style="@style/progress_horizontal_my"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />
    </LinearLayout>


</LinearLayout>




  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
Android中可以使用DatePicker控件来选择单个日期,但是要选择日期范围,可以使用Material Date Range Picker库。 这个库可以在您的应用程序中实现一个美观的日期范围选择器,用户可以选择任意两个日期。此外,该库还允许您自定义外观和行为,以适应您的应用程序需求。 您可以通过在build.gradle文件中添加以下行来将此库添加到您的项目中: ``` implementation 'com.borax12.materialdaterangepicker:library:1.9' ``` 然后,您可以创建一个MaterialDatePickerDialog来显示日期选择器: ```java Calendar now = Calendar.getInstance(); MaterialDatePickerDialog.Builder builder = MaterialDatePickerDialog.Builder.dateRangePicker(); builder.setTitleText("Select date range"); builder.setSelection(new Pair<>(now.getTimeInMillis(), now.getTimeInMillis())); builder.setCalendarConstraints(limitRange().build()); builder.setOnSelectionChangedListener(new MaterialDatePicker.OnSelectionChangedListener() { @Override public void onSelectionChanged(MaterialDatePicker<?> materialDatePicker, SelectionPair<Long> selectionPair) { // Do something with the selected date range } }); builder.show(getSupportFragmentManager(), "DATE_RANGE_PICKER"); ``` 在此示例中,我们设置了默认选择当前日期,并使用setCalendarConstraints方法来限制日期范围。在onSelectionChanged回调中,您可以处理用户所选择的日期范围。 希望这可以帮助您实现所需的日期范围选择器!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值