最近项目需要用到双向的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的更多相关文章

  1. Android 打造炫目的圆形菜单 秒秒钟高仿建行圆形菜单

    原文:Android 打造炫目的圆形菜单 秒秒钟高仿建行圆形菜单 转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43131133, ...

  2. Android 打造自己的ImageLoader

    Android 打造自己的ImageLoader 学习和参考 Android开发艺术探索 https://blog.csdn.net/column/details/15318.html 郭霖大神的Gl ...

  3. Android 打造完美的侧滑菜单/侧滑View控件

    概述 Android 打造完美的侧滑菜单/侧滑View控件,完全自定义实现,支持左右两个方向弹出,代码高度简洁流畅,兼容性高,控件实用方便. 详细 代码下载:http://www.demodashi. ...

  4. Android基础控件SeekBar拖动条的使用

    1.简介 SeekBar继承ProgressBar,相关属性和三种不同状态下的触发方法: <!--<SeekBar--> <!--android:layout_width=&q ...

  5. Android打造属于自己的数据库操作类。

    1.概述 开发Android的同学都知道sdk已经为我们提供了一个SQLiteOpenHelper类来创建和管理SQLite数据库,通过写一个子类去继承它,就可以方便的创建.管理数据库.但是当我们需要 ...

  6. Android课程---Android 如何用滑杆(SeekBar)组件设置图片颜色的透明度(转)

    Android系统支持的颜色是由4个值组成的,前3个为RGB,也就是我们常说的三原色(红.绿.蓝),最后一个值是A,也就是Alpha.这4个值都在0~255之间.颜色值越小,表示该颜色越淡,颜色值越大 ...

  7. android学习笔记八——SeekBar

    SeekBar——拖动条 拖动条(SeekBar)组件与ProgressBar水平形式的显示进度条类似,不过其最大的区别在于,拖动条可以由用户自己进行手工的调节,例如当用户需要调整播放器音量或者电影的 ...

  8. android打造万能的适配器(转)

    荒废了两天,今天与大家分享一个ListView的适配器 前段时间在学习慕课网的视频,觉得这种实现方式较好,便记录了下来,最近的项目中也使用了多次,节省了大量的代码,特此拿来与大家分享一下. 还是先看图 ...

  9. Android 拖动条(SeekBar)实例 附完整demo项目代码

    1.拖动条的事件 实现SeekBar.OnSeekBarChangeListener接口.需要监听三个事件:数值改变(onProgressChanged)开始拖动(onStartTrackingTou ...

随机推荐

  1. 六星经典CSAPP-笔记(7)加载与链接(上)

    六星经典CSAPP-笔记(7)加载与链接 1.对象文件(Object File) 1.1 文件类型 对象文件有三种形式: 可重定位对象文件(Relocatable object file):包含二进制 ...

  2. DB 查询分析器7.01 新增的保存执行结果到多个文件功能

        1      引言   中国本土程序员马根峰(CSDN专访马根峰:海量数据处理与分析大师的中国本土程序员)推出的个人作品----万能数据库查询分析器,中文版本DB 查询分析器.英文版本< ...

  3. Android开发艺术探索——第二章:IPC机制(中)

    Android开发艺术探索--第二章:IPC机制(中) 好的,我们继续来了解IPC机制,在上篇我们可能就是把理论的知识写完了,然后现在基本上是可以实战了. 一.Android中的IPC方式 本节我们开 ...

  4. Dynamics CRM2013 从外部系统取到CRM系统的用户头像

    CRM从2013开始引入了entityimage的概念,具体这个字段怎么设置的,图像是怎么上传的这里就不谈了.说实在的这玩意在项目中没啥用,所以也没去关注,直到最近遇到了个难题,要在外部系统去获取这个 ...

  5. Dynamics CRM2016 Web API之Retrieve Multiple

    之前的博文只介绍了通过记录的primary key来查询单条记录或者单个属性值,本篇介绍多条记录的查询方法 var filter = "?$filter=name eq '123'" ...

  6. ubuntu挂载的NTFS文件编译失败问题

    错误: 编译Android源代码时候出现,权限拒绝的错误 解决方法: sudo apt-get install ntfs-config sudo ntfs-config 我的微信二维码如下,欢迎交流讨 ...

  7. iOS开发出错whose view is not in the window hierarchy!的解决

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 一个简单的单窗口App在运行时出现错误: 2016-04-07 ...

  8. Android简易实战教程--第十一话《获取手机所有应用信息Engine类详解》

    如果想要获取系统手机应用的详细信息,那么下边代码可以直接作为模板使用.笔者对每一行代码都做了注解,供您参考.直接上代码: package com.example.itydl.engines; impo ...

  9. 算法之路(二)呈现O(logN)型的三个算法

    典型时间复杂度 我们知道算法的执行效率,可以从它的时间复杂度来推算出一二.而典型的时间复杂度有哪些类型呢? 由上图,可以看出,除了常数时间复杂度外,logN型的算法效率是最高的.今天就介绍三种非常ea ...

  10. 【Android应用开发】Android Studio 错误集锦 -- 将所有的 AS 错误集合到本文

    . 一. 编译错误 1. "AndroidManifest.xml file not found" 错误 (1) 报错信息 报错信息 : -- Message Make : Inf ...