Android自定义View实现拖动选择按钮
程序员文章站
2024-03-01 21:12:40
本文为大家分享了android实现拖动选择按钮的具体代码,供大家参考,具体内容如下
效果图
view代码
第一步:自定义属性
本文为大家分享了android实现拖动选择按钮的具体代码,供大家参考,具体内容如下
效果图
view代码
第一步:自定义属性
<declare-styleable name="dragview"> <attr name="icon_drag" format="reference"/> <attr name="color_circle" format="color"/> <attr name="dot_num" format="integer"/> </declare-styleable>
第二步:自定义圆形
public class circleview extends view { /** * 默认颜色 */ private final int default_color = color.ltgray; /** * 默认半径dp */ private final float default_radius = 32; private int mcolor; private paint mcirclepaint; private float mradius; private float mcenterx; private float mcentery; public circleview(context context) { this(context, null); } public circleview(context context, attributeset attrs) { this(context, attrs, 0); } public circleview(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); typedarray array = context.obtainstyledattributes(attrs, r.styleable.dragview); mcolor = array.getcolor(r.styleable.dragview_color_circle,default_color); mcirclepaint = new paint(); mcirclepaint.setcolor(mcolor); mcentery = mcenterx = mradius = getmeasuredwidth() == 0?default_radius:getmeasuredwidth()/2; array.recycle(); } public float getradius(){ return mradius; } public int getcolor() { return mcolor; } @override protected void ondraw(canvas canvas) { canvas.drawcircle(mcenterx,mcentery,mradius,mcirclepaint); } }
第三步:自定义拖动按钮
public class dragview extends relativelayout implements view.ontouchlistener { private drawable mdragicon;//拖动图标 private imageview mdragview;//拖动图标imageview private int mcirclecolor;//圆的颜色 private context mcontext;//上下文 private int mdotnum;//节点数量 private int mwidth;//组件的宽度 private int mhight;//组件的高度 private int mcircleradius;//园的半径 private int mdragwidth;//拖动图标的宽度 private int mlinewidth,mlineheight;//中间线的长宽 private float mstartx;//开始拖动的屏幕坐标 private float mcurx;//开始拖动的触点坐标 private float mminx;//拖动范围的最小值 private float mmaxx;//拖动范围的最大值 private onnodeselect monnodeselect;//回调接口 public dragview(context context) { this(context,null); } public dragview(context context, attributeset attrs) { this(context, attrs,0); } public dragview(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); typedarray array=context.obtainstyledattributes(attrs, r.styleable.dragview); mdragicon=array.getdrawable(r.styleable.dragview_icon_drag); mcirclecolor=array.getcolor(r.styleable.dragview_color_circle,color.white); mdotnum=array.getint(r.styleable.dragview_dot_num,2); array.recycle(); mcontext=context; initview(); } /** *视图初始化,这个方法的作用是把所有的视图添加进来,并做一些初始化的配置 * 其实可以用layoutinflater把xml的布局文件加载进来,这样比较简便 */ public void initview(){ for (int i=0;i<mdotnum;i++){ circleview circleview=new circleview(mcontext); circleview.setontouchlistener(this); addview(circleview); } view view=new view(mcontext); view.setbackgroundcolor(mcirclecolor); addview(view); // todo: 2016/4/21 top not right mdragview=new imageview(mcontext); mdragview.setimagedrawable(mdragicon); mdragview.setontouchlistener(this); addview(mdragview); } /** *这一步主要是为了测量、配置每个view的大小,以便于后面触摸事件的处理 */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); mwidth=getmeasuredwidth(); mhight=getmeasuredheight(); mcircleradius=dp2px(mcontext,32); mdragwidth=dp2px(mcontext,50); mlinewidth=mwidth-mdragwidth; mlineheight=mcircleradius/2; int count=getchildcount(); for (int i=0;i<count;i++){ view view=getchildat(i); linearlayout.layoutparams params; if (view instanceof circleview){ params=new linearlayout.layoutparams(mcircleradius,mcircleradius); view.setlayoutparams(params); }else if (view instanceof imageview){ params=new linearlayout.layoutparams(mdragwidth,mdragwidth); view.setlayoutparams(params); }else { params=new linearlayout.layoutparams(mlinewidth,mlineheight); view.setlayoutparams(params); } } } /** *这一步主要是为了放置每个view的位置,如果用layoutinflater加载布局文件,那这一步就可以省略了 */ @override protected void onlayout(boolean changed, int l, int t, int r, int b) { // super.onlayout(changed, l, t, r, b); if (changed){ int count =getchildcount(); int dleft=0; int dtop=mhight/2-mdragwidth/2; int cleft=mdragwidth/2-mcircleradius/2; int ctop=dtop+mdragwidth/2-mcircleradius/2; int lleft=mdragwidth/2; int ltop=dtop+mdragwidth/2-mlineheight/2; mminx=dleft; mmaxx=dleft+mlinewidth; int cindex=0; int cspace=0; for (int i=0;i<count;i++){ view view=getchildat(i); if (view instanceof circleview){ cleft=cleft+cspace; view.layout(cleft,ctop,cleft+mcircleradius,ctop+mcircleradius); cindex++; cspace=cindex*mlinewidth; }else if (view instanceof imageview){ view.layout(dleft,dtop,dleft+mdragwidth,dtop+mdragwidth); }else { view.layout(lleft,ltop,lleft+mlinewidth,ltop+mlineheight); } } } } /** *触碰事件的处理,这是自定义view比较重要的地方 */ @override public boolean ontouch(view v, motionevent event) { if (v instanceof imageview){ switch (event.getaction()) { case motionevent.action_down: mstartx = (int) event.getrawx(); mcurx = v.gettranslationx();//获取view的偏移量 v.setpressed(true); break; case motionevent.action_move: float x = mcurx + event.getrawx() - mstartx; if (x >= 0 && x <= mmaxx - mminx) { v.settranslationx(mcurx + event.getrawx() - mstartx); } break; case motionevent.action_up: case motionevent.action_cancel: int distance=(int) (event.getrawx()-mstartx); if (distance>0){ if (math.abs(distance)>mlinewidth/2){ v.settranslationx(mcurx + event.getrawx() - mstartx); setanim(mlinewidth,1); }else { v.settranslationx(mcurx + event.getrawx() - mstartx); setanim(0,0); } }else if (distance<0){ if (math.abs(distance)>mlinewidth/2){ v.settranslationx(mcurx + event.getrawx() - mstartx); setanim(0,0); }else { v.settranslationx(mcurx + event.getrawx() - mstartx); setanim(mlinewidth,1); } } break; } }else if (v instanceof circleview){ switch (event.getaction()) { case motionevent.action_up: if (event.getrawx()>getdisplaywidth()/2){ setanim(mlinewidth,1); }else { setanim(0,0); } break; } } return true; } //设置平移动画 private void setanim(float movex, final int scrollposition) { objectanimator animator = objectanimator.offloat(mdragview, "translationx", mdragview.gettranslationx(), movex); animator.setduration(300); animator.start(); if (monnodeselect != null) { monnodeselect.onnodeselect(scrollposition); } } public void setnodeselectlistener(onnodeselect onnodeselect) { monnodeselect = onnodeselect; } //事件回调接口 public interface onnodeselect { void onnodeselect(int position); } //dp转px public int dp2px(context context, float dpvalue) { final float scale = context.getresources().getdisplaymetrics().density; return (int) (dpvalue * scale + 0.5f); } //获取屏幕宽度 public int getdisplaywidth(){ displaymetrics metrics=new displaymetrics(); ((activity)mcontext).getwindowmanager().getdefaultdisplay().getmetrics(metrics); return metrics.widthpixels; } }
使用方法
布局文件:
<com.pengkv.apple.weight.dragview android:id="@+id/view_drag" android:layout_width="200dp" app:icon_drag="@drawable/ic_drag" app:color_circle="#cccccc" app:dot_num="2" android:layout_height="60dp"/>
页面代码:
dragview=(dragview)view.findviewbyid(r.id.view_drag); dragview.setnodeselectlistener(new dragview.onnodeselect() { @override public void onnodeselect(int position) { toast.maketext(getactivity(),"我选择了"+position,toast.length_short).show(); } });
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。