欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android双向选择控件DoubleSeekBar使用详解

程序员文章站 2022-06-28 12:29:22
本文实例为大家分享了android双向选择控件doubleseekbar的使用方法,供大家参考,具体内容如下先看效果图1.doubleslideseekbarpublic class doublesl...

本文实例为大家分享了android双向选择控件doubleseekbar的使用方法,供大家参考,具体内容如下

先看效果图

Android双向选择控件DoubleSeekBar使用详解

1.doubleslideseekbar

public class doubleslideseekbar extends view {
 /**
 * 线条(进度条)的宽度
 */
 private int linewidth;
 /**
 * 线条(进度条)的长度
 */
 private int linelength = 400;
 /**
 * 字所在的高度 100$
 */
 private int textheight;
 /**
 * 游标 图片宽度
 */
 private int imagewidth;
 /**
 * 游标 图片高度
 */
 private int imageheight;
 /**
 * 是否有刻度线
 */
 private boolean hasrule;
 /**
 * 左边的游标是否在动
 */
 private boolean islowermoving;
 /**
 * 右边的游标是否在动
 */
 private boolean isuppermoving;
 /**
 * 字的大小 100$
 */
 private int textsize;
 /**
 * 字的颜色 100$
 */
 private int textcolor;
 /**
 * 两个游标内部 线(进度条)的颜色
 */
 private int incolor = color.blue;
 /**
 * 两个游标外部 线(进度条)的颜色
 */
 private int outcolor = color.blue;
 /**
 * 刻度的颜色
 */
 private int rulecolor = color.blue;
 /**
 * 刻度上边的字 的颜色
 */
 private int ruletextcolor = color.blue;
 /**
 * 左边图标的图片
 */
 private bitmap bitmaplow;
 /**
 * 右边图标 的图片
 */
 private bitmap bitmapbig;
 /**
 * 左边图标所在x轴的位置
 */
 private int slidelowx;
 /**
 * 右边图标所在x轴的位置
 */
 private int slidebigx;
 /**
 * 图标(游标) 高度
 */
 private int bitmapheight;
 /**
 * 图标(游标) 宽度
 */
 private int bitmapwidth;
 /**
 * 加一些padding 大小酌情考虑 为了我们的自定义view可以显示完整
 */
 private int paddingleft = 100;
 private int paddingright = 100;
 private int paddingtop = 50;
 private int paddingbottom = 10;
 /**
 * 线(进度条) 开始的位置
 */
 private int linestart = paddingleft;
 /**
 * 线的y轴位置
 */
 private int liney;
 /**
 * 线(进度条)的结束位置
 */
 private int lineend = linelength + paddingleft;
 /**
 * 选择器的最大值
 */
 private int bigvalue = 100;
 /**
 * 选择器的最小值
 */
 private int smallvalue = 0;
 /**
 * 选择器的当前最小值
 */
 private float smallrange;
 /**
 * 选择器的当前最大值
 */
 private float bigrange;
 /**
 * 单位 元
 */
 private string unit = " ";
 /**
 * 单位份数
 */
 private int equal = 20;
 /**
 * 刻度单位 $
 */
 private string ruleunit = " ";
 /**
 * 刻度上边文字的size
 */
 private int ruletextsize = 20;
 /**
 * 刻度线的高度
 */
 private int rulelineheight = 20;
 private paint linepaint;
 private paint bitmappaint;
 private paint textpaint;
 private paint paintrule;
 
 public doubleslideseekbar(context context) {
 this(context, null);
 }
 
 public doubleslideseekbar(context context, @nullable attributeset attrs) {
 this(context, attrs, 0);
 }
 
 public doubleslideseekbar(context context, @nullable attributeset attrs, int defstyleattr) {
 super(context, attrs, defstyleattr);
 typedarray typedarray = context.gettheme().obtainstyledattributes(attrs, r.styleable.doubleslideseekbar, defstyleattr, 0);
 int size = typedarray.getindexcount();
 for (int i = 0; i < size; i++) {
  int type = typedarray.getindex(i);
  switch (type) {
  case r.styleable.doubleslideseekbar_incolor:
   incolor = typedarray.getcolor(type, color.black);
   break;
  case r.styleable.doubleslideseekbar_lineheight:
   linewidth = (int) typedarray.getdimension(type, dip2px(getcontext(), 10));
   break;
  case r.styleable.doubleslideseekbar_outcolor:
   outcolor = typedarray.getcolor(type, color.yellow);
   break;
  case r.styleable.doubleslideseekbar_textcolor:
   textcolor = typedarray.getcolor(type, color.blue);
   break;
  case r.styleable.doubleslideseekbar_textsize:
   textsize = typedarray.getdimensionpixelsize(type, (int) typedvalue.applydimension(
    typedvalue.complex_unit_sp, 16, getresources().getdisplaymetrics()));
   break;
  case r.styleable.doubleslideseekbar_imagelow:
   bitmaplow = bitmapfactory.decoderesource(getresources(), typedarray.getresourceid(type, 0));
   break;
  case r.styleable.doubleslideseekbar_imagebig:
   bitmapbig = bitmapfactory.decoderesource(getresources(), typedarray.getresourceid(type, 0));
   break;
  case r.styleable.doubleslideseekbar_imageheight:
   imageheight = (int) typedarray.getdimension(type, dip2px(getcontext(), 20));
   break;
  case r.styleable.doubleslideseekbar_imagewidth:
   imagewidth = (int) typedarray.getdimension(type, dip2px(getcontext(), 20));
   break;
  case r.styleable.doubleslideseekbar_hasrule:
   hasrule = typedarray.getboolean(type, false);
   break;
  case r.styleable.doubleslideseekbar_rulecolor:
   rulecolor = typedarray.getcolor(type, color.blue);
   break;
  case r.styleable.doubleslideseekbar_ruletextcolor:
   ruletextcolor = typedarray.getcolor(type, color.blue);
   break;
  case r.styleable.doubleslideseekbar_unit:
   unit = typedarray.getstring(type);
   break;
  case r.styleable.doubleslideseekbar_equal:
   equal = typedarray.getint(type, 10);
   break;
  case r.styleable.doubleslideseekbar_ruleunit:
   ruleunit = typedarray.getstring(type);
   break;
  case r.styleable.doubleslideseekbar_ruletextsize:
   ruletextsize = typedarray.getdimensionpixelsize(type, (int) typedvalue.applydimension(
    typedvalue.complex_unit_sp, 16, getresources().getdisplaymetrics()));
   break;
  case r.styleable.doubleslideseekbar_rulelineheight:
   rulelineheight = (int) typedarray.getdimension(type, dip2px(getcontext(), 10));
   break;
  case r.styleable.doubleslideseekbar_bigvalue:
   bigvalue = typedarray.getinteger(type, 100);
   break;
  case r.styleable.doubleslideseekbar_smallvalue:
   smallvalue = typedarray.getinteger(type, 100);
   break;
 
 
  default:
   break;
  }
 }
 typedarray.recycle();
 init();
 }
 
 private void init() {
 /**游标的默认图*/
 if (bitmaplow == null) {
  bitmaplow = bitmapfactory.decoderesource(getresources(), r.mipmap.ic_launcher);
 }
 if (bitmapbig == null) {
  bitmapbig = bitmapfactory.decoderesource(getresources(), r.mipmap.ic_launcher);
 }
 /**游标图片的真实高度 之后通过缩放比例可以把图片设置成想要的大小*/
 bitmapheight = bitmaplow.getheight();
 bitmapwidth = bitmaplow.getwidth();
 // 设置想要的大小
 int newwidth = imagewidth;
 int newheight = imageheight;
 // 计算缩放比例
 float scalewidth = ((float) newwidth) / bitmapwidth;
 float scaleheight = ((float) newheight) / bitmapheight;
 matrix matrix = new matrix();
 matrix.postscale(scalewidth, scaleheight);
 /**缩放图片*/
 bitmaplow = bitmap.createbitmap(bitmaplow, 0, 0, bitmapwidth, bitmapheight, matrix, true);
 bitmapbig = bitmap.createbitmap(bitmapbig, 0, 0, bitmapwidth, bitmapheight, matrix, true);
 /**重新获取游标图片的宽高*/
 bitmapheight = bitmaplow.getheight();
 bitmapwidth = bitmaplow.getwidth();
 /**初始化两个游标的位置*/
 slidelowx = linestart;
 slidebigx = lineend;
 smallrange = smallvalue;
 bigrange = bigvalue;
 if (hasrule) {
  //有刻度时 paddingtop 要加上(text高度)和(刻度线高度加刻度线上边文字的高度和) 之间的最大值
  paddingtop = paddingtop + math.max(textsize, rulelineheight + ruletextsize);
 } else {
  //没有刻度时 paddingtop 加上 text的高度
  paddingtop = paddingtop + textsize;
 }
 }
 
 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
 int width = getmymeasurewidth(widthmeasurespec);
 int height = getmymeasureheight(heightmeasurespec);
 setmeasureddimension(width, height);
 }
 
 private int getmymeasureheight(int heightmeasurespec) {
 int mode = measurespec.getmode(heightmeasurespec);
 int size = measurespec.getsize(heightmeasurespec);
 if (mode == measurespec.exactly) {
  // matchparent 或者 固定大小 view最小应为 paddingbottom + paddingtop + bitmapheight + 10 否则显示不全
  size = math.max(size, paddingbottom + paddingtop + bitmapheight + 10);
 } else {
  //wrap content
  int height = paddingbottom + paddingtop + bitmapheight + 10;
  size = math.min(size, height);
 }
 return size;
 }
 
 private int getmymeasurewidth(int widthmeasurespec) {
 int mode = measurespec.getmode(widthmeasurespec);
 int size = measurespec.getsize(widthmeasurespec);
 if (mode == measurespec.exactly) {
 
  size = math.max(size, paddingleft + paddingright + bitmapwidth * 2);
 
 } else {
  //wrap content
  int width = paddingleft + paddingright + bitmapwidth * 2;
  size = math.min(size, width);
 }
 // match parent 或者 固定大小 此时可以获取线(进度条)的长度
 linelength = size - paddingleft - paddingright - bitmapwidth;
 //线(进度条)的结束位置
 lineend = linelength + paddingleft + bitmapwidth / 2;
 //线(进度条)的开始位置
 linestart = paddingleft + bitmapwidth / 2;
 //初始化 游标位置
 slidebigx = lineend;
 slidelowx = linestart;
 return size;
 }
 
 @override
 protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 // y轴 坐标
 liney = getheight() - paddingbottom - bitmapheight / 2;
 // 字所在高度 100$
 textheight = liney - bitmapheight / 2 - 10;
// //是否画刻度
// if (hasrule) {
//  drawrule(canvas);
// }
// if (linepaint == null) {
//  linepaint = new paint();
// }
 linepaint = new paint();
 //画内部线
 linepaint.setantialias(true);
 linepaint.setstrokewidth(linewidth);
 linepaint.setcolor(incolor);
 linepaint.setstrokecap(paint.cap.round);
 canvas.drawline(slidelowx, liney, slidebigx, liney, linepaint);
 linepaint.setcolor(outcolor);
 linepaint.setstrokecap(paint.cap.round);
 //画 外部线
 canvas.drawline(linestart, liney, slidelowx, liney, linepaint);
 canvas.drawline(slidebigx, liney, lineend, liney, linepaint);
 //画游标
 if (bitmappaint == null) {
  bitmappaint = new paint();
 }
 canvas.drawbitmap(bitmaplow, slidelowx - bitmapwidth / 2, liney - bitmapheight / 2, bitmappaint);
 canvas.drawbitmap(bitmapbig, slidebigx - bitmapwidth / 2, liney - bitmapheight / 2, bitmappaint);
 //画 游标上边的字
 if (textpaint == null) {
  textpaint = new paint();
 }
 textpaint.setcolor(textcolor);
 textpaint.settextsize(textsize);
 textpaint.setantialias(true);
 canvas.drawtext(string.format("%.0f" + unit, smallrange), slidelowx - bitmapwidth / 2, textheight, textpaint);
 canvas.drawtext(string.format("%.0f" + unit, bigrange), slidebigx - bitmapwidth / 2, textheight, textpaint);
 }
 
 @override
 public boolean ontouchevent(motionevent event) {
 //事件机制
 super.ontouchevent(event);
 float nowx = event.getx();
 float nowy = event.gety();
 switch (event.getaction()) {
  case motionevent.action_down:
  //按下 在线(进度条)范围上
  boolean righty = math.abs(nowy - liney) < bitmapheight / 2;
  //按下 在左边游标上
  boolean lowslide = math.abs(nowx - slidelowx) < bitmapwidth / 2;
  //按下 在右边游标上
  boolean bigslide = math.abs(nowx - slidebigx) < bitmapwidth / 2;
  if (righty && lowslide) {
   islowermoving = true;
  } else if (righty && bigslide) {
   isuppermoving = true;
   //点击了游标外部 的线上
  } else if (nowx >= linestart && nowx <= slidelowx - bitmapwidth / 2 && righty) {
   slidelowx = (int) nowx;
   updaterange();
   postinvalidate();
  } else if (nowx <= lineend && nowx >= slidebigx + bitmapwidth / 2 && righty) {
   slidebigx = (int) nowx;
   updaterange();
   postinvalidate();
  }
  break;
  case motionevent.action_move:
  //左边游标是运动状态
  if (islowermoving) {
   //当前 x坐标在线上 且在右边游标的左边
   if (nowx <= slidebigx - bitmapwidth && nowx >= linestart - bitmapwidth / 2) {
   slidelowx = (int) nowx;
   if (slidelowx < linestart) {
    slidelowx = linestart;
   }
   //更新进度
   updaterange();
   postinvalidate();
   }
 
  } else if (isuppermoving) {
   //当前 x坐标在线上 且在左边游标的右边
   if (nowx >= slidelowx + bitmapwidth && nowx <= lineend + bitmapwidth / 2) {
   slidebigx = (int) nowx;
   if (slidebigx > lineend) {
    slidebigx = lineend;
   }
   //更新进度
   updaterange();
   postinvalidate();
 
   }
  }
  break;
  //手指抬起
  case motionevent.action_up:
  isuppermoving = false;
  islowermoving = false;
  break;
  default:
  break;
 }
 
 return true;
 }
 
 private void updaterange() {
 //当前 左边游标数值
 smallrange = computrange(slidelowx);
 //当前 右边游标数值
 bigrange = computrange(slidebigx);
 //接口 实现值的传递
 if (onrangelistener != null) {
  onrangelistener.onrange(smallrange, bigrange);
 }
 }
 
 /**
 * 获取当前值
 */
 private float computrange(float range) {
 return (range - linestart) * (bigvalue - smallvalue) / linelength + smallvalue;
 }
 
 public int dip2px(context context, float dpvalue) {
 final float scale = context.getresources().getdisplaymetrics().density;
 return (int) (dpvalue * scale + 0.5f);
 }
 
// /**
// * 画刻度
// */
// protected void drawrule(canvas canvas) {
// if (paintrule == null) {
//  paintrule = new paint();
// }
// paintrule.setstrokewidth(1);
// paintrule.settextsize(ruletextsize);
// paintrule.settextalign(paint.align.center);
// paintrule.setantialias(true);
// //遍历 equal份,画刻度
// for (int i = smallvalue; i <= bigvalue; i += (bigvalue - smallvalue) / equal) {
//  float degx = linestart + i * linelength / (bigvalue - smallvalue);
//  int degy = liney - rulelineheight;
//  paintrule.setcolor(rulecolor);
//  canvas.drawline(degx, liney, degx, degy, paintrule);
//  paintrule.setcolor(ruletextcolor);
//  canvas.drawtext(string.valueof(i) + ruleunit, degx, degy, paintrule);
// }
// }
 
 /**
 * 写个接口 用来传递最大最小值
 */
 public interface onrangelistener {
 void onrange(float low, float big);
 }
 
 private onrangelistener onrangelistener;
 
 public void setonrangelistener(doubleslideseekbar.onrangelistener onrangelistener) {
 this.onrangelistener = onrangelistener;
 }
}

2.在values文件夹中创建attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <!--线(进度条)宽度-->
 <attr name="lineheight" format="dimension" />
 <!--字的大小 100元-->
 <attr name="textsize" format="dimension" />
 <!--字的颜色 100元-->
 <attr name="textcolor" format="color" />
 <!--两个游标内部 线(进度条)的颜色-->
 <attr name="incolor" format="color" />
 <!--两个游标外部 线(进度条)的颜色-->
 <attr name="outcolor" format="color" />
 <!--左边图标的图片-->
 <attr name="imagelow" format="reference"/>
 <!--右边图标 的图片-->
 <attr name="imagebig" format="reference"/>
 <!--游标 图片宽度-->
 <attr name="imagewidth" format="dimension" />
 <!--游标 图片高度-->
 <attr name="imageheight" format="dimension" />
 <!--是否有刻度线-->
 <attr name="hasrule" format="boolean" />
 <!--刻度的颜色-->
 <attr name="rulecolor" format="color" />
 <!--刻度上边的字 的颜色-->
 <attr name="ruletextcolor" format="color" />
 <!--单位 元-->
 <attr name="unit" format="string"/>
 <!--单位份数-->
 <attr name="equal" format="integer"/>
 <!--刻度单位 $-->
 <attr name="ruleunit" format="string"/>
 <!--刻度上边文字的size-->
 <attr name="ruletextsize" format="dimension" />
 <!--刻度线的高度-->
 <attr name="rulelineheight" format="dimension" />
 <!--选择器的最大值-->
 <attr name="bigvalue" format="integer"/>
 <!--选择器的最小值-->
 <attr name="smallvalue" format="integer"/>
 <declare-styleable name="doubleslideseekbar">
  <attr name="lineheight" />
  <attr name="textsize" />
  <attr name="textcolor" />
  <attr name="incolor" />
  <attr name="outcolor" />
  <attr name="imagelow"/>
  <attr name="imagebig"/>
  <attr name="imagewidth" />
  <attr name="imageheight" />
  <attr name="hasrule" />
  <attr name="rulecolor" />
  <attr name="ruletextcolor" />
  <attr name="unit" />
  <attr name="equal" />
  <attr name="ruleunit" />
  <attr name="ruletextsize" />
  <attr name="rulelineheight" />
  <attr name="bigvalue" />
  <attr name="smallvalue" />
 </declare-styleable>
</resources> 

3.activity_main.xml布局

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 xmlns:custom="http://schemas.android.com/apk/res-auto"
 tools:context=".mainactivity"
 android:orientation="vertical">
 
 <com.xxx.xxx.doubleslideseekbar
  android:id="@+id/doubleslide_withrule"
  android:layout_margintop="20dp"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  custom:lineheight="6dp"
  custom:textsize="12sp"
  custom:textcolor="#0628e4"
  custom:incolor="#f10a0a"
  custom:outcolor="#af08e2"
  custom:imagewidth="20dp"
  custom:imageheight="20dp"
  custom:hasrule="true"
  custom:rulecolor="#0e0e0e"
  custom:ruletextcolor="#f74104"
  custom:equal="10"
  custom:ruletextsize="8sp"
  custom:rulelineheight="10dp"
  />
 <textview
  android:id="@+id/tv_min_rule"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="0"
  android:layout_margintop="10dp"></textview>
 <textview
  android:id="@+id/tv_max_rule"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="0"
  android:layout_margintop="10dp"></textview>
 
 
</linearlayout>

4.mainactivity

public class mainactivity extends appcompatactivity {
 
 private doubleslideseekbar mdoubleslidewithrule;
 private textview mtvminrule;
 private textview mtvmaxrule;
 
 @override
 protected void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.activity_main);
  mdoubleslidewithrule = (doubleslideseekbar) findviewbyid(r.id.doubleslide_withrule);
  mtvminrule = (textview) findviewbyid(r.id.tv_min_rule);
  mtvmaxrule = (textview) findviewbyid(r.id.tv_max_rule);
  setlistener();
 }
 private void setlistener() {
 
  mdoubleslidewithrule.setonrangelistener(new doubleslideseekbar.onrangelistener() {
   @override
   public void onrange(float low, float big) {
    mtvminrule.settext("最小值" + string.format("%.0f" , low));
    mtvmaxrule.settext("最大值" + string.format("%.0f" , big));
   }
  });
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。