Android双向选择控件DoubleSeekBar使用详解
程序员文章站
2022-06-28 12:29:22
本文实例为大家分享了android双向选择控件doubleseekbar的使用方法,供大家参考,具体内容如下先看效果图1.doubleslideseekbarpublic class doublesl...
本文实例为大家分享了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)); } }); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。