自定义实现了一个选定范围值的控件,刻度尺为等分的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;
-
- 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();
- }
三,绘制尺子,尺子的刻度,尺子上的位置标记控件。
绘制尺子,其中mProBaseline为尺子top的位置。尺子的range实际是两个不同的矩形框。
-
-
-
-
- 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 不 绘制
-
-
-
- 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){
-
- 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;
-
-
-
-
-
- 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;
- }
-
-
-
-
-
- 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);
-
- 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.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>