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

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

程序员文章站 2024-03-01 21:12:40
本文为大家分享了android实现拖动选择按钮的具体代码,供大家参考,具体内容如下 效果图 view代码 第一步:自定义属性

本文为大家分享了android实现拖动选择按钮的具体代码,供大家参考,具体内容如下

效果图

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

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();
  }
 });

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