当前位置: 移动技术网 > 移动技术>移动开发>Android > Android实现滑动选择控件实例代码

Android实现滑动选择控件实例代码

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

前言

最近做了个滑动选择的小控件,拿出来给大家分享一下,先上图

运行效果


实现步骤

这里分解为3个动作:down、move、up来进行分析,博主文采不好,大家直接看流程图吧!!



代码分析

前置知识

1、这个地方使用的是recyclerview的代码,使用recyclerview只能使用linearlayoutmanager,listview的运行效果稍微要比recyclerview差一些

//这里使用dispatchtouchevent,因为ontouchevent容易被ontouchlistener截取
  @override
  public boolean dispatchtouchevent(motionevent ev) {
    layoutmanager manager = getlayoutmanager();
    //获取第一个和最后一个显示的item对应的相对position
    if (manager instanceof linearlayoutmanager) {
      mfirstvisibleposition = ((linearlayoutmanager) manager).findfirstvisibleitemposition();
      mlastvisibleposition = ((linearlayoutmanager) manager).findlastvisibleitemposition();
    }
    switch (ev.getaction()) {
      case motionevent.action_down:
        //获取按下时的位置,x,y
        int startx = (int) ev.getx();
        int starty = (int) ev.gety();
        int prex = startx;
        mprey = starty;
        mprefirstvisibleposition = mfirstvisibleposition;
        mpreposition = mstartposition = pointtoposition(startx, starty);

        if (mstartposition > -1) {
          //获取当前item的view
          view child = getchildat(mstartposition);
          if (null != child) {
            //获取响应域,一般响应域里面就是一个checkbox
            view tmpcheckboxcontainer = child.findviewwithtag("checkbox_layout");
            if (null != tmpcheckboxcontainer && tmpcheckboxcontainer.getvisibility() == visible) {
              mcheckboxwidth = tmpcheckboxcontainer.getwidth();
              //获取响应域的范围,一定要用这种获取绝对位置的方式,不然会受到padding或者是margin的影响
              int[] location = new int[2];
              tmpcheckboxcontainer.getlocationonscreen(location);
              mcheckboxx = location[0];
              //判断按下的位置是否是在响应域内
              if (startx >= mcheckboxx && startx <= (mcheckboxx + mcheckboxwidth)) {
                log.d(log_tag, "dispatchtouchevent() down mstartposition: " + mstartposition);
                //设置截取事件的标志位
                misneedscrollcheck = true;
                //设置为第一次滑动,这是用作判断折返的
                misfirstmove = true;
                setstartcheckboxstate();
                //截获checkbox的点击事件,防止两次选中
                return true;
              } else {
                misneedscrollcheck = false;
              }
            } else {
              misneedscrollcheck = false;
              log.e(log_tag, "dispatchtouchevent() ", new throwable("cannot get checkboxcontainer!"));
            }

          } else {
            log.e(log_tag, "dispatchtouchevent() ", new throwable("cannot get item view!"));
          }
        }
        break;
      case motionevent.action_move:
        //获取当前位置
        int currentx = (int) ev.getx();
        int currenty = (int) ev.gety();
        //获取当前的item
        int currentposition = pointtoposition(currentx, currenty);
        //判断是否允许滑动选中
        if (misneedscrollcheck && -1 != mfirstvisibleposition && -1 != mlastvisibleposition && -1 != currentposition) {
          //判断是否在下一个item的像英语
          if ((currentposition + mfirstvisibleposition) != (mpreposition + mprefirstvisibleposition) &&
              currentx >= mcheckboxx && currentx <= (mcheckboxx + mcheckboxwidth)) {

            log.i(log_tag, "********************************** dispatchtouchevent() ********************************");
            log.d(log_tag, "dispatchtouchevent() move mcurrentposition: " + currentposition);
            log.d(log_tag, "dispatchtouchevent() move mfirstvisibleposition: " + mfirstvisibleposition);
            log.d(log_tag, "dispatchtouchevent() move mpreposition: " + mpreposition);
            log.d(log_tag, "dispatchtouchevent() move mprefirstvisibleposition: " + mprefirstvisibleposition);
            log.i(log_tag, "********************************** dispatchtouchevent() ********************************");

            //折返回来时要改变前一个的checkbox的状态

            if (misfirstmove) {
              misfirstmove = false;
              if (currenty >= mprey) {
                mupordown = false;
              } else {
                mupordown = true;
              }
            } else {
              if ((currentposition + mfirstvisibleposition) > (mpreposition + mprefirstvisibleposition) && mupordown) {
                changecheckboxstate(mpreposition);
                mupordown = false;
              } else if ((currentposition + mfirstvisibleposition) < (mpreposition + mprefirstvisibleposition) && !mupordown) {
                changecheckboxstate(mpreposition);
                mupordown = true;
              }
            }


            changecheckboxstate(currentposition);

          }

          //判断是否是在最后一个item上滑动,如果是则进行自动向下滑动,如果是在第一个上下滑动,则自动向上滑动
          //log.d(log_tag, "dispatchtouchevent() move: " + (mlastvisibleposition - mcurrentposition - mfirstvisibleposition));
          if ((mlastvisibleposition - mfirstvisibleposition - currentposition) < 1 && currenty > mprey) {
            //自动向下滑
            log.d(log_tag, "dispatchtouchevent() move mcount: " + mcount);
            view child = getchildat(currentposition);
            if (null != child && 0 == mcount % 5) {
              scrolltoposition(mlastvisibleposition + 1);
            }
            mcount++;
          } else if (currentposition < 2 && currenty < mprey) {
            //自动向上滑
            view child = getchildat(currentposition);
            log.d(log_tag, "dispatchtouchevent() move mcount: " + mcount);
            //mcount用于降低滑动的频率,频率太快容易滑动的看不清楚
            if (null != child && 0 == mcount % 5) {
              scrolltoposition(mfirstvisibleposition - 1);
            }
            mcount++;
          }
          mprey = currenty;
          mpreposition = currentposition;
          mprefirstvisibleposition = mfirstvisibleposition;

          return true;
        }
        break;

      case motionevent.action_up:
        if (misneedscrollcheck) {
          mcount = 0;
          return false;

        }
        break;


    }
    return super.dispatchtouchevent(ev);
  }

其他的代码片段

//改变开始的checkbox状态
  private void setstartcheckboxstate() {
    view child = getchildat(mstartposition);
    if (null != child) {
      viewgroup checkboxcontainer = (viewgroup) child.findviewwithtag("checkbox_layout");
      if (null != checkboxcontainer) {
        checkbox checkbox = (checkbox) checkboxcontainer.getchildat(0);
        if (null != checkbox && checkbox.getvisibility() == visible) {
          checkbox.toggle();
        }
      }

    }
  }

//判断当前item的position,相对位置
  private int pointtoposition(int x, int y) {
    rect frame = mtouchframe;
    if (frame == null) {
      mtouchframe = new rect();
      frame = mtouchframe;
    }

    final int count = getchildcount();
    for (int i = count - 1; i >= 0; i--) {
      final view child = getchildat(i);
      if (child.getvisibility() == view.visible) {
        child.gethitrect(frame);
        if (frame.contains(x, y)) {
          return i;
        }
      }
    }
    return -1;
  }
//改变position的选中状态
  public void changecheckboxstate(int position) {
    if (position < 0 || position >= getchildcount()) {
      return;
    }

    view child = getchildat(position);
    if (null != child) {
      viewgroup checkboxlayout = (viewgroup) child.findviewwithtag("checkbox_layout");
      if (null != checkboxlayout && checkboxlayout.getvisibility() == visible) {
        checkbox checkbox = (checkbox) checkboxlayout.getchildat(0);
        if (null != checkbox) {
          log.d(log_tag, "changecheckboxstate() selectcheckbox: " + position);
          //checkbox.performclick();
          checkbox.toggle();
          //checkbox.setclickable(false);
          //checkbox.callonclick();
        }
      }

    }
  }

项目源码:

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

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

相关文章:

验证码:
移动技术网