实现原理:
1、自定义View,在onDraw(Canvas canvas)中,画出2个Drawable滑动块,2个Drawable滑动条,2个Paint(text)
2、监听onTouchEvent()事件,修改滑块和滑动条的坐标,调用invalidate()来更新界面
使用方法
1、自定义View   SeekBarPressure.class
package xxxxxxxxximport android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.math.BigDecimal;
import com.zjcpo.mobileapp.R;public class SeekBarPressure extends View {private static final String TAG = "SeekBarPressure";private static final int CLICK_ON_LOW = 1;      //点击在前滑块上private static final int CLICK_ON_HIGH = 2;     //点击在后滑块上private static final int CLICK_IN_LOW_AREA = 3;private static final int CLICK_IN_HIGH_AREA = 4;private static final int CLICK_OUT_AREA = 5;private static final int CLICK_INVAILD = 0;/** private static final int[] PRESSED_STATE_SET = {* android.R.attr.state_focused, android.R.attr.state_pressed,* android.R.attr.state_selected, android.R.attr.state_window_focused, };*/private static final int[] STATE_NORMAL = {};private static final int[] STATE_PRESSED = {android.R.attr.state_pressed, android.R.attr.state_window_focused,};private Drawable hasScrollBarBg;        //滑动条滑动后背景图private Drawable notScrollBarBg;        //滑动条未滑动背景图private Drawable mThumbLow;         //前滑块private Drawable mThumbHigh;        //后滑块private int mScollBarWidth;     //控件宽度=滑动条宽度+滑动块宽度private int mScollBarHeight;    //滑动条高度private int mThumbWidth;        //滑动块宽度private int mThumbHeight;       //滑动块高度private double mOffsetLow = 0;     //前滑块中心坐标private double mOffsetHigh = 0;    //后滑块中心坐标private int mDistance = 0;      //总刻度是固定距离 两边各去掉半个滑块距离private int mThumbMarginTop = 30;   //滑动块顶部距离上边框距离,也就是距离字体顶部的距离private int mFlag = CLICK_INVAILD;private OnSeekBarChangeListener mBarChangeListener;private double defaultScreenLow = 0;    //默认前滑块位置百分比private double defaultScreenHigh = 100;  //默认后滑块位置百分比private boolean isEdit = false;     //输入框是否正在输入public SeekBarPressure(Context context) {this(context, null);}public SeekBarPressure(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SeekBarPressure(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);
//        this.setBackgroundColor(Color.BLACK);
Resources resources = getResources();notScrollBarBg = resources.getDrawable(R.drawable.seekbarpressure_bg_progress);hasScrollBarBg = resources.getDrawable(R.drawable.seekbarpressure_bg_normal);mThumbLow = resources.getDrawable(R.drawable.seekbarpressure_thumb);mThumbHigh = resources.getDrawable(R.drawable.seekbarpressure_thumb);mThumbLow.setState(STATE_NORMAL);mThumbHigh.setState(STATE_NORMAL);mScollBarWidth = notScrollBarBg.getIntrinsicWidth();mScollBarHeight = notScrollBarBg.getIntrinsicHeight();mThumbWidth = mThumbLow.getIntrinsicWidth();mThumbHeight = mThumbLow.getIntrinsicHeight();}//默认执行,计算view的宽高,在onDraw()之前protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int width = measureWidth(widthMeasureSpec);
//        int height = measureHeight(heightMeasureSpec);mScollBarWidth = width;mOffsetHigh = width - mThumbWidth / 2;mOffsetLow = mThumbWidth / 2;mDistance = width - mThumbWidth;mOffsetLow = formatDouble(defaultScreenLow / 100 * (mDistance ))+ mThumbWidth / 2;mOffsetHigh = formatDouble(defaultScreenHigh / 100 * (mDistance)) + mThumbWidth / 2;setMeasuredDimension(width, mThumbHeight + mThumbMarginTop+2);}private int measureWidth(int measureSpec) {int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);//wrap_contentif (specMode == MeasureSpec.AT_MOST) {}//fill_parent或者精确值else if (specMode == MeasureSpec.EXACTLY) {}return specSize;}private int measureHeight(int measureSpec) {int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);int defaultHeight = 100;//wrap_contentif (specMode == MeasureSpec.AT_MOST) {}//fill_parent或者精确值else if (specMode == MeasureSpec.EXACTLY) {defaultHeight = specSize;}return defaultHeight;}protected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);}protected void onDraw(Canvas canvas) {super.onDraw(canvas);Paint text_Paint = new Paint();text_Paint.setTextAlign(Paint.Align.CENTER);text_Paint.setColor(Color.RED);text_Paint.setTextSize(20);int aaa = mThumbMarginTop + mThumbHeight / 2 - mScollBarHeight / 2;int bbb = aaa + mScollBarHeight;//白色,不会动notScrollBarBg.setBounds(mThumbWidth / 2, aaa, mScollBarWidth - mThumbWidth / 2, bbb);notScrollBarBg.draw(canvas);//蓝色,中间部分会动hasScrollBarBg.setBounds((int)mOffsetLow, aaa, (int)mOffsetHigh, bbb);hasScrollBarBg.draw(canvas);//前滑块mThumbLow.setBounds((int)(mOffsetLow - mThumbWidth / 2), mThumbMarginTop, (int)(mOffsetLow + mThumbWidth / 2), mThumbHeight + mThumbMarginTop);mThumbLow.draw(canvas);//后滑块mThumbHigh.setBounds((int)(mOffsetHigh - mThumbWidth / 2), mThumbMarginTop, (int)(mOffsetHigh + mThumbWidth / 2), mThumbHeight + mThumbMarginTop);mThumbHigh.draw(canvas);double progressLow = formatDouble((mOffsetLow - mThumbWidth / 2) * 100 / mDistance);double progressHigh = formatDouble((mOffsetHigh - mThumbWidth / 2) * 100 / mDistance);
//            Log.d(TAG, "onDraw-->mOffsetLow: " + mOffsetLow + "  mOffsetHigh: " + mOffsetHigh   + "  progressLow: " + progressLow + "  progressHigh: " + progressHigh);canvas.drawText((int) progressLow + "", (int)mOffsetLow - 2 - 2, 15, text_Paint);canvas.drawText((int) progressHigh + "", (int)mOffsetHigh - 2, 15, text_Paint);if (mBarChangeListener != null) {if (!isEdit) {mBarChangeListener.onProgressChanged(this, progressLow, progressHigh);}}}@Overridepublic boolean onTouchEvent(MotionEvent e) {//按下if (e.getAction() == MotionEvent.ACTION_DOWN) {if (mBarChangeListener != null) {mBarChangeListener.onProgressBefore();isEdit = false;}mFlag = getAreaFlag(e);
//            Log.d(TAG, "e.getX: " + e.getX() + "mFlag: " + mFlag);
//            Log.d("ACTION_DOWN", "------------------");if (mFlag == CLICK_ON_LOW) {mThumbLow.setState(STATE_PRESSED);} else if (mFlag == CLICK_ON_HIGH) {mThumbHigh.setState(STATE_PRESSED);} else if (mFlag == CLICK_IN_LOW_AREA) {mThumbLow.setState(STATE_PRESSED);//如果点击0-mThumbWidth/2坐标if (e.getX() < 0 || e.getX() <= mThumbWidth/2) {mOffsetLow = mThumbWidth/2;} else if (e.getX() > mScollBarWidth - mThumbWidth/2) {
//                    mOffsetLow = mDistance - mDuration;mOffsetLow = mThumbWidth/2 + mDistance;} else {mOffsetLow = formatDouble(e.getX());
//                    if (mOffsetHigh<= mOffsetLow) {
//                        mOffsetHigh = (mOffsetLow + mDuration <= mDistance) ? (mOffsetLow + mDuration)
//                                : mDistance;
//                        mOffsetLow = mOffsetHigh - mDuration;
//                    }
                }} else if (mFlag == CLICK_IN_HIGH_AREA) {mThumbHigh.setState(STATE_PRESSED);
//                if (e.getX() < mDuration) {
//                    mOffsetHigh = mDuration;
//                    mOffsetLow = mOffsetHigh - mDuration;
//                } else if (e.getX() >= mScollBarWidth - mThumbWidth/2) {
//                    mOffsetHigh = mDistance + mThumbWidth/2;if(e.getX() >= mScollBarWidth - mThumbWidth/2) {mOffsetHigh = mDistance + mThumbWidth/2;} else {mOffsetHigh = formatDouble(e.getX());
//                    if (mOffsetHigh <= mOffsetLow) {
//                        mOffsetLow = (mOffsetHigh - mDuration >= 0) ? (mOffsetHigh - mDuration) : 0;
//                        mOffsetHigh = mOffsetLow + mDuration;
//                    }
                }}//设置进度条
            refresh();//移动move} else if (e.getAction() == MotionEvent.ACTION_MOVE) {
//            Log.d("ACTION_MOVE", "------------------");if (mFlag == CLICK_ON_LOW) {if (e.getX() < 0 || e.getX() <= mThumbWidth/2) {mOffsetLow = mThumbWidth/2;} else if (e.getX() >= mScollBarWidth - mThumbWidth/2) {mOffsetLow = mThumbWidth/2 + mDistance;mOffsetHigh = mOffsetLow;} else {mOffsetLow = formatDouble(e.getX());if (mOffsetHigh - mOffsetLow <= 0) {mOffsetHigh = (mOffsetLow <= mDistance+mThumbWidth/2) ? (mOffsetLow) : (mDistance+mThumbWidth/2);}}} else if (mFlag == CLICK_ON_HIGH) {if (e.getX() <  mThumbWidth/2) {mOffsetHigh = mThumbWidth/2;mOffsetLow = mThumbWidth/2;} else if (e.getX() > mScollBarWidth - mThumbWidth/2) {mOffsetHigh = mThumbWidth/2 + mDistance;} else {mOffsetHigh = formatDouble(e.getX());if (mOffsetHigh - mOffsetLow <= 0) {mOffsetLow = (mOffsetHigh >= mThumbWidth/2) ? (mOffsetHigh) : mThumbWidth/2;}}}//设置进度条
            refresh();//抬起} else if (e.getAction() == MotionEvent.ACTION_UP) {
//            Log.d("ACTION_UP", "------------------");
            mThumbLow.setState(STATE_NORMAL);mThumbHigh.setState(STATE_NORMAL);if (mBarChangeListener != null) {mBarChangeListener.onProgressAfter();}//这两个for循环 是用来自动对齐刻度的,注释后,就可以自由滑动到任意位置
//            for (int i = 0; i < money.length; i++) {
//                 if(Math.abs(mOffsetLow-i* ((mScollBarWidth-mThumbWidth)/ (money.length-1)))<=(mScollBarWidth-mThumbWidth)/(money.length-1)/2){
//                     mprogressLow=i;
//                     mOffsetLow =i* ((mScollBarWidth-mThumbWidth)/(money.length-1));
//                     invalidate();
//                     break;
//                }
//            }
//
//            for (int i = 0; i < money.length; i++) {
//                  if(Math.abs(mOffsetHigh-i* ((mScollBarWidth-mThumbWidth)/(money.length-1) ))<(mScollBarWidth-mThumbWidth)/(money.length-1)/2){
//                      mprogressHigh=i;
//                       mOffsetHigh =i* ((mScollBarWidth-mThumbWidth)/(money.length-1));
//                       invalidate();
//                       break;
//                }
//            }
        }return true;}public int getAreaFlag(MotionEvent e) {int top = mThumbMarginTop;int bottom = mThumbHeight + mThumbMarginTop;if (e.getY() >= top && e.getY() <= bottom && e.getX() >= (mOffsetLow - mThumbWidth / 2) && e.getX() <= mOffsetLow + mThumbWidth / 2) {return CLICK_ON_LOW;} else if (e.getY() >= top && e.getY() <= bottom && e.getX() >= (mOffsetHigh - mThumbWidth / 2) && e.getX() <= (mOffsetHigh + mThumbWidth / 2)) {return CLICK_ON_HIGH;} else if (e.getY() >= top&& e.getY() <= bottom&& ((e.getX() >= 0 && e.getX() < (mOffsetLow - mThumbWidth / 2)) || ((e.getX() > (mOffsetLow + mThumbWidth / 2))&& e.getX() <= ((double) mOffsetHigh + mOffsetLow) / 2))) {return CLICK_IN_LOW_AREA;} else if (e.getY() >= top&& e.getY() <= bottom&& (((e.getX() > ((double) mOffsetHigh + mOffsetLow) / 2) && e.getX() < (mOffsetHigh - mThumbWidth / 2)) || (e.getX() > (mOffsetHigh + mThumbWidth/2) && e.getX() <= mScollBarWidth))) {return CLICK_IN_HIGH_AREA;} else if (!(e.getX() >= 0 && e.getX() <= mScollBarWidth && e.getY() >= top && e.getY() <= bottom)) {return CLICK_OUT_AREA;} else {return CLICK_INVAILD;}}//更新滑块private void refresh() {invalidate();}//设置前滑块的值    public void setProgressLow(double  progressLow) {this.defaultScreenLow = progressLow;mOffsetLow = formatDouble(progressLow / 100 * (mDistance ))+ mThumbWidth / 2;isEdit = true;refresh();}//设置后滑块的值public void setProgressHigh(double  progressHigh) {this.defaultScreenHigh = progressHigh;mOffsetHigh = formatDouble(progressHigh / 100 * (mDistance)) + mThumbWidth / 2;isEdit = true;refresh();}public void setOnSeekBarChangeListener(OnSeekBarChangeListener mListener) {this.mBarChangeListener = mListener;}//回调函数,在滑动时实时调用,改变输入框的值public interface OnSeekBarChangeListener {//滑动前public void onProgressBefore();//滑动时public void onProgressChanged(SeekBarPressure seekBar, double progressLow,double progressHigh);//滑动后public void onProgressAfter();}/*    private int formatInt(double value) {BigDecimal bd = new BigDecimal(value);BigDecimal bd1 = bd.setScale(0, BigDecimal.ROUND_HALF_UP);return bd1.intValue();}*/public static double formatDouble(double pDouble) {BigDecimal bd = new BigDecimal(pDouble);BigDecimal bd1 = bd.setScale(2, BigDecimal.ROUND_HALF_UP);pDouble = bd1.doubleValue();return pDouble;}}

2、布局调用 xxx.xml

        <com.xxx.SeekBarPressureandroid:id="@+id/seekBar_tg2"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentTop="true"android:layout_marginBottom="10dp"android:layout_marginLeft="10dp"android:layout_marginRight="10dp" />

3、在Activity中实现XxxActivity.class

seekBarPressures = (SeekBarPressure) findViewById(R.id.seekBar_tg2);seekBarPressures.setOnSeekBarChangeListener(new SeekBarPressure.OnSeekBarChangeListener() {@Overridepublic void onProgressBefore() {isScreen = true;}@Overridepublic void onProgressChanged(SeekBarPressure seekBar, double progressLow, double progressHigh) {editTexts_min.setText((int) progressLow + "");editTexts_max.setText((int) progressHigh + "");}@Overridepublic void onProgressAfter() {isScreen = false;}});

注意:seekBar的父容器必须LinearLayout,别问我为什么,我也不知道。反正如果是Rinearlayout的话,滑动会不正常,我曹了,为这问题搞了整整3个小时

android 双向滑动 seekbar相关推荐

  1. Android双向滑动菜单完全解析,教你如何一分钟实现双向滑动特效

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9671609 记得在很早之前,我写了一篇关于Android滑动菜单的文章,其中有一个 ...

  2. Android双向滑动控件

    Android双向滑动控件 kaxi4it 关注 一 效果图 二 使用方法 由于新版jcenter强制添加组织还要收费貌似,所以改用jitpack了 最新版本号 在你root的gradle中添加引用 ...

  3. 超酷的Android 侧滑(双向滑动菜单)效果

    Java代码   下面看看我们如何使用它,达到我们想要的效果 public class MainActivity extends Activity { /** * 双向滑动菜单布局 */ privat ...

  4. android 滑动顶部固定,android view滑动到顶部悬停

    千万不要再根据滑动的高度来控制控件的显示隐藏来实现悬停效果了,推荐一个超级方便的实现悬停效果的 CoordinatorLayout+AppBarLayout完美实现悬停效果 例子如下 android: ...

  5. android double比较大小吗,Android双向选择控件DoubleSeekBar使用详解

    本文实例为大家分享了Android双向选择控件DoubleSeekBar的使用方法,供大家参考,具体内容如下 先看效果图 1.DoubleSlideSeekBar public class Doubl ...

  6. Android中使用SeekBar拖动条实现改变图片透明度

    场景 效果 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 将布局改为Lin ...

  7. php框架加滑动条,IOS_iOS实现双向滑动条效果,最近做项目,碰到一种双向滑 - phpStudy...

    iOS实现双向滑动条效果 最近做项目,碰到一种双向滑动条,自己实现了一下,随便写一下思路,方便以后开发,避免重复写代码,以后粘贴就行了.封装了一下,代码如下: #import typedef NSSt ...

  8. android中seekbar 常用属性列表,随笔–android中修改SeekBar控件默认显示-Fun言

    布局文件中相关代码如下: android:id="@+id/seekbar" android:layout_width="match_parent" andro ...

  9. Android的滑动分析

    Android的滑动分析 滑动应该可以说是Android中最常见的一种视觉效果,也是View编写中的关键,本篇文章就来分析一下Android中滑动的实现方式. 滑动通常分为计算位移以及执行滑动两部分, ...

最新文章

  1. Mac用Java写出hello,mac中c#的helloworld
  2. Android动态修改选中和不选中的Button图片颜色
  3. HDR (automatic exposure control + Tonemapping + Bloom)
  4. 【Derby 系列】Apache Derby 功能特点
  5. 代码整洁之道(一)最佳实践小结 1
  6. 国家航天局+华为云:做地球的守护者
  7. php驱动下载好后安装在哪里,没网如何安装网卡驱动
  8. 基于QItemDelegate的例子2 trackeEditorDelegate
  9. javaweb——总结
  10. HTTP-Runoob:教程
  11. 系统部门岗位关联表_155页,房地产公司最为系统的岗位说明书,敬请收藏
  12. IntelliJ IDEA多项目共用一个Tomcat
  13. KKK下拉框lookupedit绑定数据时,添加一条固定数据
  14. imageJ使用手册
  15. 如何使用腾讯云存储图片
  16. 关于赛马的问题,25匹赛出前3名或者前5名
  17. NDT Matching 算法学习
  18. C#实现触摸屏自定义键盘
  19. 关于程序员的问题,我是看大佬说的不是我说的。
  20. 微信小程序openid如何获得IP白名单的方法

热门文章

  1. ffmpeg 解码音频(aac、mp3)输出pcm文件
  2. 关于Tomcat双击startup.bat文件一闪而过问题
  3. goland远程调试Docker
  4. Redis运维和开发学习目录
  5. 汇编:实现日历星期数查询工具
  6. 被面试官问的Android问题难倒了,成功入职字节跳动
  7. 渣本毕业两年经验,看这一篇就够了!
  8. 安卓开发入门到精通!免费Android高级工程师学习资源,系列篇
  9. 大话数据结构——查找
  10. 微信小程序页面跳转、逻辑层模块化