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 ...
随机推荐
- cassandra 3.x官方文档(3)---gossip通信协议及故障检测与恢复
写在前面 cassandra3.x官方文档的非官方翻译.翻译内容水平全依赖本人英文水平和对cassandra的理解.所以强烈建议阅读英文版cassandra 3.x 官方文档.此文档一半是翻译,一半是 ...
- Java经典设计模式之五大创建型模式(附实例和详解)
一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥 ...
- Spring MVC 实践 - Base
Spring MVC 实践 标签 : Java与Web Spring Web MVC Spring-Web-MVC是一种基于请求驱动的轻量级Web-MVC设计模式框架, Spring MVC使用MVC ...
- 微信小程序发布
一.操作步骤 (1)打开[微信开发者工具]->新建一个默认项目->点击[项目]->点击[上传] (2)使用微信小程序公众平台管理员扫描二维码,在手机微信上点击[确认上传] (3)输入 ...
- 硬件模块化机器人操作系统 Hardware Robot Operating System (H-ROS)
原文网址:http://www.ros.org/news/2016/10/hardware-robot-operating-system-h-ros.html 推荐网址:https://h-ros.c ...
- hbase高性能读取数据
有时需要从hbase中一次读取大量的数据,同时对实时性有较高的要求.可以从两方面进行考虑:1.hbase提供的get方法提供了批量获取数据方法,通过组装一个list<Get> gets即可 ...
- 第一行代码阅读笔记---详解分析第一个Android程序
以下是我根据作者的思路,创建的第一个Android应用程序,由于工具强大,代码都自动生成了,如下: package com.example.first_app; import android.os.B ...
- Swift基础之init方法,实例方法,类方法(静态方法)的使用(多标签Demo)
Xcode更新过后,有些方法都进行了改变,Demo中有变化的都进行了简单的标记,具体以后遇见再说 创建一个UIView类,用init方法创建两种类型,显示多标签,创建静态方法进行调用,创建类方法进行调 ...
- 插件占坑,四大组件动态注册前奏(三) 系统BroadCast的注册发送流程
转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52204143 前言:为什么要了解系统Activity,Service,BroadCas ...
- iOS7 CookBook精彩瞬间(二)NSSet、通过Subscript访问类成员等
1.NSSet的用法 ①NSSet是一种无序集合,基于hash实现,可以在线性时间复杂度内查找某个元素,如果要让元素有序,应当使用NSOrderedSet,要让集合可变,与NSArray类似,使用NS ...