android 打造不同的Seekbar详解手机开发
2023-06-13 09:20:14 时间
最近项目需要用到双向的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();
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
5887.html
app程序应用开发手机开发无线开发移动端开发相关文章
- android换机备份,安卓手机备份迁移指南
- android进阶之了解Android系统与开机过程
- Android studio更新后出现警告:Warning:The `android.dexOptions.incremental` property is deprecated and it has
- 基于Android TextureView与SurfaceTexture实现相机Camera拍照预览与保存照片详解手机开发
- Android Glide数据更新及内存缓存、硬盘缓存清理详解手机开发
- Android 7.0 应用启动流程分析详解手机开发
- 实现Android手机摄像头的自动对焦详解手机开发
- Android获取手机中外置内存卡、内置内存卡、手机内存路径详解手机开发
- [android] 练习样式主题自定义activity切换动画详解手机开发
- [android] 安卓消息推送的几种实现方式详解手机开发
- [android] 常用数据适配器SimpleAdapter详解手机开发
- Android 多级弹窗实现详解手机开发
- Android 纵向跑马灯滚动效果详解手机开发
- android抓屏详解手机开发
- android客户端和服务端js交互详解手机开发
- android-async-http框架源码分析详解手机开发
- 论Android代码加固的意义和hook详解手机开发
- android 防止反编译的若干方法详解手机开发
- Android动画及图片的缩放和旋转详解手机开发
- android虚线边框详解手机开发
- Android 写一个属于自己的音视频播放器详解手机开发
- 7月Android手机性价比榜:Redmi连夺三冠
- Android手机获取root权限并实现关机重启功能的方法