android 打造不同的Seekbar
最近项目需要用到双向的seekbar,网上找了好多野不能达到要求,偶然一次机会看到了大众点评的例子,然后我最他做了优化,并对常用的seekbar做了总结.
向上两张图:
比如双向seekbar
public class SimpleRangeSeekBar extends View { private int lineWidth = 5; private int textSize = 25; private int inRangeColor = 0xff26b5f5; private int outRangeColor = 0xffC2C2C2; 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 boolean isLowerMoving = false; private boolean isUpperMoving = false; private OnRangeChangedListener onRangeChangedListener; private int paddingLeft = 50; private int paddingRight = 50; private int paddingTop = 10; private int paddingBottom = 10; private int lineHeight=20; private int lineLength = Utils.getScreenWidth(getContext())-paddingLeft-paddingRight-50; private int lineStart = paddingLeft; private int lineEnd = lineLength + paddingLeft; private int smallRange = 0; private int maxRange = 100; private int textHeight; public SimpleRangeSeekBar(Context context, AttributeSet attrs) { this(context, attrs,-1); } public SimpleRangeSeekBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AttributeSet attrs, int defStyle) { initAttr(context, attrs, defStyle); initView(); } private void initView() { lowerBmp = BitmapFactory.decodeResource(getResources(), R.drawable.seekbar_n); upperBmp = BitmapFactory.decodeResource(getResources(), R.drawable.seekbar_n); bmpWidth = upperBmp.getWidth(); bmpHeight = upperBmp.getHeight(); lowerCenterX = lineStart; upperCenterX = lineEnd; lineHeight = getHeight() - paddingBottom - lowerBmp.getHeight() / 2; textHeight = lineHeight + lowerBmp.getHeight() / 2 + 10; } private void initAttr(Context context, AttributeSet attrs, int defStyle) { TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.RangeSeekBar, defStyle, 0); // lineWidth = typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_layout_width, UIUtils.getScreenWidth(getContext())-paddingLeft-paddingRight-50); // lineHeight=typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_layout_height,15); paddingLeft = typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_paddingLeft, 50); paddingRight= typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_paddingRight, 50); paddingTop= typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_paddingTop, 30); paddingBottom= typedArray.getDimensionPixelSize(R.styleable.RangeSeekBar_paddingBottom, 20); smallRange = typedArray.getInt(R.styleable.RangeSeekBar_line_small_range,0); maxRange = typedArray.getInt(R.styleable.RangeSeekBar_line_max_range,100); typedArray.recycle(); } 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; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { widthMeasureSpec = measureWidth(widthMeasureSpec); heightMeasureSpec = measureHeight(heightMeasureSpec); setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); } @Override protected 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); // 画范围文字 drawText(canvas); } private void drawText(Canvas canvas) { Paint textPaint = new Paint(); textPaint.setColor(textColor); textPaint.setTextSize(textSize); textPaint.setAntiAlias(true); textPaint.setStrokeWidth(lineWidth); canvas.drawText(String.valueOf(smallRange), lowerCenterX - bmpWidth / 2, textHeight, textPaint); canvas.drawText(String.valueOf(maxRange), upperCenterX - bmpWidth / 2, textHeight, textPaint); } @Override public 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 int computeRange(int range) { return (range - lineStart) * (maxRange - smallRange) / lineLength + smallRange; } private void updateRange() { smallRange = computeRange(lowerCenterX); maxRange = computeRange(upperCenterX); if (null != onRangeChangedListener) { onRangeChangedListener.onRangeChanged(smallRange, maxRange); } } public void setOnRangeChangedListener( OnRangeChangedListener onRangeChangedListener) { this.onRangeChangedListener = onRangeChangedListener; } public interface OnRangeChangedListener { void onRangeChanged(int lowRange, int maxRange); } }
为了方便大家使用我使用了自定义属性方便大家配置。
大家有兴趣还是去我的链接下载吧
http://download.csdn.net/detail/xiangzhihong8/9578539
android 打造不同的Seekbar的更多相关文章
- Android 打造炫目的圆形菜单 秒秒钟高仿建行圆形菜单
原文:Android 打造炫目的圆形菜单 秒秒钟高仿建行圆形菜单 转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43131133, ...
- Android 打造自己的ImageLoader
Android 打造自己的ImageLoader 学习和参考 Android开发艺术探索 https://blog.csdn.net/column/details/15318.html 郭霖大神的Gl ...
- Android 打造完美的侧滑菜单/侧滑View控件
概述 Android 打造完美的侧滑菜单/侧滑View控件,完全自定义实现,支持左右两个方向弹出,代码高度简洁流畅,兼容性高,控件实用方便. 详细 代码下载:http://www.demodashi. ...
- Android基础控件SeekBar拖动条的使用
1.简介 SeekBar继承ProgressBar,相关属性和三种不同状态下的触发方法: <!--<SeekBar--> <!--android:layout_width=&q ...
- Android打造属于自己的数据库操作类。
1.概述 开发Android的同学都知道sdk已经为我们提供了一个SQLiteOpenHelper类来创建和管理SQLite数据库,通过写一个子类去继承它,就可以方便的创建.管理数据库.但是当我们需要 ...
- Android课程---Android 如何用滑杆(SeekBar)组件设置图片颜色的透明度(转)
Android系统支持的颜色是由4个值组成的,前3个为RGB,也就是我们常说的三原色(红.绿.蓝),最后一个值是A,也就是Alpha.这4个值都在0~255之间.颜色值越小,表示该颜色越淡,颜色值越大 ...
- android学习笔记八——SeekBar
SeekBar——拖动条 拖动条(SeekBar)组件与ProgressBar水平形式的显示进度条类似,不过其最大的区别在于,拖动条可以由用户自己进行手工的调节,例如当用户需要调整播放器音量或者电影的 ...
- android打造万能的适配器(转)
荒废了两天,今天与大家分享一个ListView的适配器 前段时间在学习慕课网的视频,觉得这种实现方式较好,便记录了下来,最近的项目中也使用了多次,节省了大量的代码,特此拿来与大家分享一下. 还是先看图 ...
- Android 拖动条(SeekBar)实例 附完整demo项目代码
1.拖动条的事件 实现SeekBar.OnSeekBarChangeListener接口.需要监听三个事件:数值改变(onProgressChanged)开始拖动(onStartTrackingTou ...
随机推荐
- Unity3D各平台Application.xxxPath的路径
前几天我们游戏在一个同事的Android手机上启动时无法正常进入,经查发现Application.temporaryCachePath和Application.persistentDataPath返回 ...
- 安卓 LayoutInflater参数作用
方法重载1 public View inflate (int resource, ViewGroup root, boolean attachToRoot) 方法重载2 public View inf ...
- Xcode Organizational Identifiers
操作系统(不管是iOS或是OS X)使用bundle标识去唯一标识你的应用.Bundle标识由一个组织id和你App的名字组成. 一般的,组织id是你域名的反转.如果你的域名是example.com那 ...
- TV Metro界面(仿泰捷视频TV版)源码解析
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52822499 前言:上一篇介绍了 ...
- Compass实战 站内搜索
今天早上打算对这两天学习的Lucene以及Compass总结一下,想来想去,还是写个小项目来验证最好了.于是就有了今天的这篇文章.难易程度适合对于Compass或者Lucene刚入门的童鞋,大牛看到后 ...
- Java遍历时删除List、Set、Map中的元素(源码分析)
在对List.Set.Map执行遍历删除或添加等改变集合个数的操作时,不能使用普通的while.for循环或增强for.会抛出ConcurrentModificationException异常或者没有 ...
- linux shell 判断文件是否存在等符号
-a file exists. -b file exists and is a block special file. -c file exists and is a character spec ...
- iOS开发关于适配iOS10以及Xcode8的相关新知识
一.证书管理 用Xcode8打开工程后,比较明显的就是下图了,这个是苹果的新特性,可以帮助我们自动管理证书.建议大家勾选这个Automatically manage signing(Ps.但是在bea ...
- 使用git-flow来帮助管理git代码
对git不熟悉的我,经常把git提交搞得很乱,导致在master上有许多无用的commit,最终决定好好地看一下git的使用教程,却不小心发现了还有一个git-flow的工具可以帮助我管理好git项目 ...
- Android开发小问题集
由于安卓系统比较复杂,开发中会发中会碰见各种小问题,在此做一些记录,只要觉得有必要就会添加进来. 1.触屏鼠标模式和触屏模式 开发android4.3高通400平台时,用atmel_max 640T作 ...