当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义View实现拖动选择按钮

Android自定义View实现拖动选择按钮

2019年07月24日  | 移动技术网移动技术  | 我要评论

本文为大家分享了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();
  }
 });

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网