Android自定义View实现等级滑动条的实例
程序员文章站
2023-10-26 20:40:34
android自定义view实现等级滑动条的实例
实现效果图:
思路:
首先绘制直线,然后等分直线绘制点;
绘制点的时候把x值存到集合中...
android自定义view实现等级滑动条的实例
实现效果图:
思路:
首先绘制直线,然后等分直线绘制点;
绘制点的时候把x值存到集合中。
然后绘制背景图片,以及图片上的数字。
点击事件down的时候,换小图片为大图片。move的时候跟随手指移动。
up的时候根据此时的x计算最近的集合中的点,然后自动吸附回去。
1,自定义属性
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="beautyseekbarview"> <attr name="valuecountent" format="integer"/> <attr name="padding" format="dimension"/> <attr name="pointcolor" format="color"/> <attr name="linecolor" format="color"/> <attr name="smallpic" format="reference"/> <attr name="bigpic" format="reference"/> </declare-styleable> </resources>
然后获取属性:
/** * 获得我们所定义的自定义样式属性 */ typedarray a = context.gettheme().obtainstyledattributes(attrs, r.styleable.beautyseekbarview, defstyleattr, 0); //等级数量即点的个数 valuecountent=a.getinteger(r.styleable.beautyseekbarview_valuecountent, 5); //点的颜色 pointcolor = a.getcolor(r.styleable.beautyseekbarview_pointcolor, color.white); //线的颜色 linecolor = a.getcolor(r.styleable.beautyseekbarview_linecolor, color.white); //小图片 smallpic=a.getresourceid(r.styleable.beautyseekbarview_smallpic, r.drawable.ic_launcher); //滑动过程中的大图片 bigpic=a.getresourceid(r.styleable.beautyseekbarview_bigpic, r.drawable.ic_launcher); //控件的内边距 viewpadding=a.getdimensionpixelsize(r.styleable.beautyseekbarview_padding, (int) typedvalue.applydimension( typedvalue.complex_unit_sp, 16, getresources().getdisplaymetrics())); a.recycle();
2.绘制
@override protected void ondraw(canvas canvas) { // todo auto-generated method stub super.ondraw(canvas); float pointx = 0; float pointy=getheight()/2; canvas.drawline(0+getpaddingleft(),pointy, getwidth()-getpaddingright(), pointy, linepaint); //绘制直线 int averagelength =(getwidth()-getpaddingleft()-getpaddingright())/(valuecountent-1); for(int i=0;i<valuecountent;i++){ pointx=i*averagelength+getpaddingleft(); canvas.drawpoint(pointx, pointy, pointpaint);//绘制点 if(pointlist!=null && pointlist.size()<valuecountent){ pointlist.add(pointx);//把每个点都放入集合中; } } sepoolth.release(); canvas.drawbitmap(mbitmap, bitmappointx-bitmapwidth/2, pointy-bitmapheight/2, null);//绘制拖动的图片 canvas.drawtext(""+index, bitmappointx, (getheight() - fontmetrics.ascent - fontmetrics.descent) / 2, textpaint); //绘制文字 }
全部代码如下
import java.util.arraylist; import java.util.hashmap; import java.util.concurrent.semaphore; import android.r.integer; import android.animation.valueanimator; import android.content.context; import android.content.res.typedarray; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.graphics.paint.fontmetricsint; import android.util.attributeset; import android.util.log; import android.util.typedvalue; import android.view.motionevent; import android.view.view; public class beautyseekbarview extends view { private semaphore sepoolth=new semaphore(0);//信号量,解决并发问题 private int valuecountent;//等级点的数量 private int pointcolor; private int linecolor; private bitmap mbitmap; private int bitmapwidth; private int bitmapheight; private float bitmappointx; private arraylist<float> pointlist;//储存画出的点的point值 private hashmap<float, float> mhashmap;////把差值和listx当做键值对保存起来,便于后期找出 private int index=1;//索引 private float mlistx;//移动后最小的点 private int smallpic; private int bigpic; private int viewpadding; private paint pointpaint; private paint linepaint; private paint textpaint; private fontmetricsint fontmetrics; public beautyseekbarview(context context) { this(context,null); } public beautyseekbarview(context context, attributeset attrs) { this(context, attrs,0); } public beautyseekbarview(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); /** * 获得我们所定义的自定义样式属性 */ typedarray a = context.gettheme().obtainstyledattributes(attrs, r.styleable.beautyseekbarview, defstyleattr, 0); //等级数量即点的个数 valuecountent=a.getinteger(r.styleable.beautyseekbarview_valuecountent, 5); //点的颜色 pointcolor = a.getcolor(r.styleable.beautyseekbarview_pointcolor, color.white); //线的颜色 linecolor = a.getcolor(r.styleable.beautyseekbarview_linecolor, color.white); //小图片 smallpic=a.getresourceid(r.styleable.beautyseekbarview_smallpic, r.drawable.ic_launcher); //滑动过程中的大图片 bigpic=a.getresourceid(r.styleable.beautyseekbarview_bigpic, r.drawable.ic_launcher); //控件的内边距 viewpadding=a.getdimensionpixelsize(r.styleable.beautyseekbarview_padding, (int) typedvalue.applydimension( typedvalue.complex_unit_sp, 16, getresources().getdisplaymetrics())); a.recycle(); initdata();//初始化数据 initpaint();//初始化画笔 } public void initdata() { // valuecountent=7; // pointcolor=color.white; // linecolor=color.white; // setbackgroundcolor(color.black); setpadding(viewpadding, viewpadding, viewpadding, viewpadding); bitmappointx=getpaddingleft(); mbitmap=bitmapfactory.decoderesource(getresources(), smallpic); bitmapwidth=mbitmap.getwidth(); bitmapheight=mbitmap.getheight(); pointlist=new arraylist<float>(); mhashmap=new hashmap<float, float>(); } public void initpaint() { pointpaint=new paint(); pointpaint.setcolor(pointcolor); pointpaint.setstyle(paint.style.fill); pointpaint.setstrokewidth(10); pointpaint.setstrokejoin(paint.join.round); pointpaint.setstrokecap(paint.cap.round); pointpaint.setantialias(true); linepaint=new paint(); linepaint.setcolor(linecolor); linepaint.setstyle(paint.style.stroke); linepaint.setstrokewidth(4); linepaint.setantialias(true); textpaint=new paint(); textpaint.setstrokewidth(3); textpaint.settextsize(24); textpaint.setcolor(color.white); textpaint.settextalign(paint.align.center); fontmetrics = textpaint.getfontmetricsint(); textpaint.setantialias(true); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { // todo auto-generated method stub super.onmeasure(widthmeasurespec, heightmeasurespec); } @override protected void ondraw(canvas canvas) { // todo auto-generated method stub super.ondraw(canvas); float pointx = 0; float pointy=getheight()/2; canvas.drawline(0+getpaddingleft(),pointy, getwidth()-getpaddingright(), pointy, linepaint); //绘制直线 int averagelength =(getwidth()-getpaddingleft()-getpaddingright())/(valuecountent-1); for(int i=0;i<valuecountent;i++){ pointx=i*averagelength+getpaddingleft(); canvas.drawpoint(pointx, pointy, pointpaint);//绘制点 if(pointlist!=null && pointlist.size()<valuecountent){ pointlist.add(pointx);//把每个点都放入集合中; } } sepoolth.release(); canvas.drawbitmap(mbitmap, bitmappointx-bitmapwidth/2, pointy-bitmapheight/2, null);//绘制拖动的图片 canvas.drawtext(""+index, bitmappointx, (getheight() - fontmetrics.ascent - fontmetrics.descent) / 2, textpaint); //绘制文字 } long starttime = 0; @override public boolean ontouchevent(motionevent event) { //获取手指的操作--》按下、移动、松开 int action = event.getaction(); switch (action) { case motionevent.action_down: starttime=system.currenttimemillis(); mbitmap=bitmapfactory.decoderesource(getresources(), bigpic); bitmapwidth=mbitmap.getwidth(); bitmapheight=mbitmap.getheight(); textpaint.settextsize(30); //invalidate(); break; case motionevent.action_move: long endtimemove=system.currenttimemillis(); if(endtimemove-starttime>100){//如果按下,抬起时间过大才认为是拖动,要执行动画。 bitmappointx=event.getx(); updateindex(bitmappointx); invalidate(); } break; case motionevent.action_up: long endtime=system.currenttimemillis(); bitmappointx=event.getx(); mbitmap=bitmapfactory.decoderesource(getresources(),smallpic); bitmapwidth=mbitmap.getwidth(); bitmapheight=mbitmap.getheight(); textpaint.settextsize(24); if(endtime-starttime>200){//如果按下,抬起时间过大才认为是拖动,要执行动画。 updatebitmapui(bitmappointx); }else{ bitmappointx=updateindex(bitmappointx); invalidate(); } starttime = 0; break; } return true; } //更新索引 public float updateindex(float pointx){ float lastvalue=100000; float currentvalue=0; float minvalue=0; for(float listx:pointlist){ currentvalue= math.abs(pointx-listx); mhashmap.put(currentvalue, listx);//把差值和listx当做键值对保存起来,便于后期找出 minvalue=math.min(lastvalue,currentvalue); lastvalue=minvalue; } if(mhashmap.containskey(minvalue)){ mlistx=mhashmap.get(minvalue); }else{ log.e("beautyseekbarview", "updatebitmapui--->mhashmap.containskey(minvalue) is null"); return -1; } if(pointlist.contains(mlistx)){ index=pointlist.indexof(mlistx)+1; if(mlistener!=null){ mlistener.getindex(index); } }else{ log.e("beautyseekbarview", "updatebitmapui--->pointlist.contains(mlistx) is null"); return -1; } return mlistx; } //当手指抬起后更新bitmap的位置 private void updatebitmapui(float pointx2) { mlistx=updateindex(pointx2); //执行动画 valueanimator anim = valueanimator.offloat(pointx2, mlistx); anim.setduration(50); anim.addupdatelistener(new valueanimator.animatorupdatelistener() { @override public void onanimationupdate(valueanimator animation) { bitmappointx =(float) animation.getanimatedvalue(); invalidate(); } }); anim.start(); } //设置等级点的数量 public void pointvaluecountent(int countent){ if(countent<2){ valuecountent=2; }else{ valuecountent=countent; } invalidate(); } //设置默认位置 public void setpointlocation(final int location){ new thread(new runnable() { @override public void run() { try { sepoolth.acquire(); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } if(location>0&&pointlist!=null&& !pointlist.isempty()){ bitmappointx=pointlist.get(location-1); postinvalidate(); } } }).start(); } //提供接口回调,获取索引 private indexlistener mlistener=null; public interface indexlistener{ void getindex(int index); } public void setindexlistener(indexlistener listener){ mlistener=listener; } }
外部调用:
xml:
<com.example.hello.beautyseekbarview android:id="@+id/myview" android:layout_centervertical="true" android:layout_width="match_parent" android:layout_height="100dp" ws:padding="20dp" ws:valuecountent="6" ws:pointcolor="#ffffff" ws:linecolor="#ffffff" ws:smallpic="@drawable/beauty_seekbar_point" ws:bigpic="@drawable/beauty_seekbar_point_big"/>
java:
@override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); initview(); beautyseekbarview.setpointlocation(2) ; // } private void initview() { mtextview=(textview) findviewbyid(r.id.tv); beautyseekbarview=(beautyseekbarview) findviewbyid(r.id.myview); beautyseekbarview.setindexlistener(new indexlistener() { @override public void getindex(int index) { mtextview.settext("index="+index); } }); }
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!