View的事件体系_view的滑动冲突解决

本文介绍了如何解决Android中View的滑动冲突问题,主要涉及两种方法:外部拦截法和内部拦截法。外部拦截法通过重写父容器的onInterceptTouchEvent方法,决定是否拦截事件。内部拦截法则让所有事件先传递给子元素,子元素根据需要决定是否消耗事件,否则回传给父元素处理。文中还解释了为何父元素不应拦截ACTION_DOWN事件,以确保事件能正确传递给子元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所有的view的滑动冲突都可以用如下2种方式来解决:
外部拦截法和内部拦截法

1.外部拦截法:
所谓外部拦截法是指点击事件都先经过父容器的拦截处理,如果父容器需要此事件就拦截,如果不要此事件就不拦截,外部拦截发法需要重写父容器的onInterceptTouchEvent方法,在内部做相应的拦截即可,外代码如下

 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
      boolean intercept = false;
      int x = (int) ev.getRawX();
      int y = (int) ev.getRawY();
      switch (ev.getAction()) {
          case MotionEvent.ACTION_DOWN:
              intercept = false;
              break;
          case MotionEvent.ACTION_MOVE:
              if (父元素需要当前事件) {
                  intercept = true;
              } else {
                  intercept = false;
              }
              break;

          case MotionEvent.ACTION_UP:
              //up事件本身没有多大的意义,默认不拦截
              intercept = false;
              break;

          default:
              break;

      }
      return intercept;
  }

,这里对上述代码在描述一下:在onInterceptTouchEvent方法中,首先是ACTION_DOWN事件,父容器必须返回false,即不拦截down事件,因为如果父容器拦截了down事件,那么后续的move和up事件就都会交给父容器处理,这时候就再没法传递给子元素了,其次是move事件,这个事件可根据需求来决定是否拦截,如果父容器拦截就返回true,否则返回false,最后是up事件,这里必须返回false,因为up事件本事没有太多意义

2.内部拦截法:
内部拦截法是指父容器不拦截任何事情,所有的事件都传第给子元素,如果子元素需要此事件就直接消耗掉,否则就通过设置getParent().requestDisallowInterceptTouchEvent(false) 交由父元素处理,父元素和子元素都要有所改动
子元素的伪代码如下(我们需要重写子元素的dispatchTouchEvent方法)

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int x = (int) ev.getRawX();
        int y = (int) ev.getRawY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
              //让父元素把所有的事件都先给子元素
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_MOVE:
                if (子元素不要此事件/父容器需要此点击事件) {
                    //false;让父元素去拦截事件
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;

            case MotionEvent.ACTION_UP:
                break;

            default:
                break;

        }
        return super.dispatchTouchEvent(ev);
    }

当面对不同的滑动策略时,我们只需要修改里面的条件即可,其他不需要做改动,而对于父元素也要默认拦截除了action_down事件以外的其他事件,这样当子元素调用parent.requestDisallowInterceptTouchEvent(false)方法时,父元素才能继续拦截所需的事件
(为什么父元素不拦截子元素的down事件呢,因为如果父元素拦截了down事件,子元素就不会接受到事件了,后续的事件就都交给父元素处理了)
父元素的修改如下:

 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
    int action=ev.getAction();
    if( action=MotionEvent.ACTION_MOVE){
       //不拦截事件
       return false
    }else{
      //父元素想拦截事件,
      //当子元素设置成getParent().requestDisallowInterceptTouchEvent(false);父元素就可以拿到事件了,
      //如果是true,父元素就拿不到事件
      return true;
    }      
}

至于具体的实例Demo,容我后续在接着补上去啦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值