1.概述

    Android中自带的SeekBar可以用于一定范围内的筛选[0,progress],而大众点评中有个范围选择控件,可以实现[a,b]范围内的选择,今天自己模仿其做了一个。

2.效果对比图

3.功能

    用户可以滑动两个按钮进行范围的选择,还可以点击按钮两侧没有被选择的范围,以点击的位置作为其最新位置。

4.实现代码

package com.example.qq.test.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import com.example.qq.R;/** * Description: 实现范围滑杠选择器(RangeSeekBar)。 SeekBar上有两个滑块,一个选择最小值,一个选择最大值,从而选择了一个范围(range)。 *  * @author danDingCongRong * @Version 1.0.0 * @Created at 2014-7-24 14:37:56 * @Modified by [作者] on [修改日期] */public class RangeSeekBar extends View {private float lineWidth = 5.0f;private float textSize = 25.0f;private int inRangeColor = 0xffff0000;private int outRangeColor = 0xff777777;private int textColor = 0xff0000ff;private int textMarginBottom = 10;private int lowerCenterX;private int upperCenterX;private int bmpWidth;private int bmpHeight;private Bitmap lowerBmp;private Bitmap upperBmp;private Paint inRangePaint;private Paint outRangePaint;private Paint bmpPaint;private Paint textPaint;private boolean isLowerMoving = false;private boolean isUpperMoving = false;private OnRangeChangedListener onRangeChangedListener;private int paddingLeft = 50;private int paddingRight = 50;private int paddingTop = 50;private int paddingBottom = 10;private int lineHeight;private int lineLength = 400;private int lineStart = paddingLeft;private int lineEnd = lineLength + paddingLeft;private float smallValue = 0.0f;private float bigValue = 100.0f;private float smallRange = smallValue;private float bigRange = bigValue;private int textHeight;public RangeSeekBar(Context context) {super(context);init();}public RangeSeekBar(Context context, AttributeSet attrs) {super(context, attrs);init();}public RangeSeekBar(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init();}private void init() {lowerBmp = BitmapFactory.decodeResource(getResources(),R.drawable.test_range_seek_bar_imb);upperBmp = BitmapFactory.decodeResource(getResources(),R.drawable.test_range_seek_bar_imb);bmpWidth = upperBmp.getWidth();bmpHeight = upperBmp.getHeight();lowerCenterX = lineStart;upperCenterX = lineEnd;lineHeight = getHeight() - paddingBottom - lowerBmp.getHeight() / 2;textHeight = lineHeight + lowerBmp.getHeight() / 2 + 10;}private void initPaint() {// 绘制范围内的线条inRangePaint = new Paint();inRangePaint.setAntiAlias(true);inRangePaint.setStrokeWidth(lineWidth);inRangePaint.setColor(inRangeColor);// 绘制范围外的线条outRangePaint = new Paint();outRangePaint.setAntiAlias(true);outRangePaint.setStrokeWidth(lineWidth);outRangePaint.setColor(outRangeColor);// 画图片滑块bmpPaint = new Paint();// 画范围文字textPaint = new Paint();textPaint.setColor(textColor);textPaint.setTextSize(textSize);textPaint.setAntiAlias(true);textPaint.setStrokeWidth(lineWidth);}private int measureWidth(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.EXACTLY) {result = specSize;} else {result = paddingLeft + paddingRight + bmpWidth * 2;if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}}return result;}private int measureHeight(int measureHeight) {int result = 0;int specMode = MeasureSpec.getMode(measureHeight);int specSize = MeasureSpec.getSize(measureHeight);if (specMode == MeasureSpec.EXACTLY) {result = bmpHeight * 2;} else {result = bmpHeight + paddingTop;if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}}return result;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {widthMeasureSpec = measureWidth(widthMeasureSpec);heightMeasureSpec = measureHeight(heightMeasureSpec);setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);bmpWidth = upperBmp.getWidth();bmpHeight = upperBmp.getHeight();lineHeight = getHeight() - paddingBottom - lowerBmp.getHeight() / 2;textHeight = lineHeight - bmpHeight / 2 - textMarginBottom;// 画线Paint linePaint = new Paint();linePaint.setAntiAlias(true);linePaint.setStrokeWidth(lineWidth);// 绘制处于图片滑块之间线段linePaint.setColor(inRangeColor);canvas.drawLine(lowerCenterX, lineHeight, upperCenterX, lineHeight,linePaint);// 绘制处于图片滑块两端的线段linePaint.setColor(outRangeColor);canvas.drawLine(lineStart, lineHeight, lowerCenterX, lineHeight,linePaint);canvas.drawLine(upperCenterX, lineHeight, lineEnd, lineHeight,linePaint);// 画图片滑块Paint bmpPaint = new Paint();canvas.drawBitmap(lowerBmp, lowerCenterX - bmpWidth / 2, lineHeight- bmpHeight / 2, bmpPaint);canvas.drawBitmap(lowerBmp, upperCenterX - bmpWidth / 2, lineHeight- bmpHeight / 2, bmpPaint);// 画范围文字Paint textPaint = new Paint();textPaint.setColor(textColor);textPaint.setTextSize(textSize);textPaint.setAntiAlias(true);textPaint.setStrokeWidth(lineWidth);canvas.drawText(String.format("¥%.0f", smallRange), lowerCenterX- bmpWidth / 2, textHeight, textPaint);canvas.drawText(String.format("¥%.0f", bigRange), upperCenterX- bmpWidth / 2, textHeight, textPaint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {super.onTouchEvent(event);float xPos = event.getX();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 如果按下的位置在垂直方向没有与图片接触,则不会滑动滑块float yPos = event.getY();if (Math.abs(yPos - lineHeight) > bmpHeight / 2) {return false;}// 表示当前按下的滑块是左边的滑块if (Math.abs(xPos - lowerCenterX) < bmpWidth / 2) {isLowerMoving = true;}// //表示当前按下的滑块是右边的滑块if (Math.abs(xPos - upperCenterX) < bmpWidth / 2) {isUpperMoving = true;}// 单击左边滑块的左边线条时,左边滑块滑动到对应的位置if (xPos >= lineStart && xPos <= lowerCenterX - bmpWidth / 2) {lowerCenterX = (int) xPos;updateRange();postInvalidate();}// 单击右边滑块的右边线条时, 右边滑块滑动到对应的位置if (xPos <= lineEnd && xPos >= upperCenterX + bmpWidth / 2) {upperCenterX = (int) xPos;updateRange();postInvalidate();}break;case MotionEvent.ACTION_MOVE:// 滑动左边滑块时if (isLowerMoving) {if (xPos >= lineStart && xPos < upperCenterX - bmpWidth) {lowerCenterX = (int) xPos;updateRange();postInvalidate();}}// 滑动右边滑块时if (isUpperMoving) {if (xPos > lowerCenterX + bmpWidth && xPos < lineEnd) {upperCenterX = (int) xPos;updateRange();postInvalidate();}}break;case MotionEvent.ACTION_UP:// 修改滑块的滑动状态为不再滑动isLowerMoving = false;isUpperMoving = false;break;default:break;}return true;}// 计算指定滑块对应的范围值private float computRange(float range) {return (range - lineStart) * (bigValue - smallValue) / lineLength+ smallValue;}// 滑动滑块的过程中,更新滑块上方的范围标识private void updateRange() {smallRange = computRange(lowerCenterX);bigRange = computRange(upperCenterX);if (null != onRangeChangedListener) {onRangeChangedListener.onRangeChanged(smallRange, bigRange);}}// 注册滑块范围值改变事件的监听public void setOnRangeChangedListener(OnRangeChangedListener onRangeChangedListener) {this.onRangeChangedListener = onRangeChangedListener;}// 公共接口,用户回调接口范围值的改变public interface OnRangeChangedListener {public void onRangeChanged(float lowerRange, float upperRange);}}

5.测试代码

package com.example.qq.test.activity;import android.app.Activity;import android.os.Bundle;import android.view.Window;import com.example.qq.R;import com.example.qq.test.view.RangeSeekBar;import com.example.qq.test.view.RangeSeekBar.OnRangeChangedListener;/** * Description: 测试范围滑杆的效果 *  * @author danDingCongRong * @Version 1.0.0 * @Created at 2014-7-24 16:31:13 * @Modified by [作者] on [修改日期] */public class TestRangeSeekarActivity extends Activity {private RangeSeekBar rangeSeekBar;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.test_range_seekbar);initView();}private void initView() {rangeSeekBar = (RangeSeekBar) findViewById(R.id.rangeSeekBar);rangeSeekBar.setOnRangeChangedListener(new OnRangeChangedListener() {@Overridepublic void onRangeChanged(float lowerRange, float upperRange) {;}});}}


注:

1.后期需要利用自定义属性设置其各个属性值;

2.在手机适配方面还需要改进;

3.为用户提供更多的接口。





更多相关文章

  1. Android(安卓)特色开发,基于位置的服务
  2. Zxing二维码自定义修改关键代码
  3. Android实现贪吃蛇游戏一:游戏界面及控制
  4. android 更改avd路径
  5. android ListView使用的三种方法汇总(通过继承BaseAdapter,使用Si
  6. Android定位入门(1)了解定位管理器--LocationManager 类
  7. android 拼图小游戏
  8. 关于Android中的位置服务解读
  9. Android(安卓)Studio 完美修改应用包名

随机推荐

  1. android的触摸屏事件
  2. Theme.NoTitleBar问题
  3. Android_linux下android platforms下载地
  4. Android(安卓)VNC Server on G1 (PC 远程
  5. 使用SDK Manager更新时出现问题
  6. android拨打电话
  7. Android监听消息通知栏点击事件
  8. Android手机震动抖动效果的实现
  9. checkbox 文字与多选框的对齐问题
  10. 打开Android(安卓)Studio报错,Unable to c