View的事件分发机制

1.点击事件的传递规则
     点击事件的分发过程是由三个很重要的方法来共同完成
@Override
public boolean dispatchTouchEvent (MotionEvent ev) {
   
return super .dispatchTouchEvent(ev) ;
}

@Override
public boolean onInterceptTouchEvent (MotionEvent ev) {
   
return super .onInterceptTouchEvent(ev) ;
}

@Override
public boolean onTouchEvent (MotionEvent event) {
   
return super .onTouchEvent(event) ;
}

public boolean dispatchTouchEvent(MotionEvent ev){}
用来进行事件分发。如果事件能够传递给当前view,那么此方法一定会被调用,返回结果受当前view的onTouchEvent和下级的dispatchTouchEvent方法影响,表示是否消耗当前事件

public boolean onInterceptTouchEvent(MotionEvent event){}
内部调用,用来判断是否拦截某个事件,如果当前view拦截了某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件

public boolean onTouchEvent(MotionEvent event){}
dispatchTouchEvent方法内部被调用, onTouchEvent 用来处理触摸事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前view无法再次接收到事件

画了个流程图如下:

一个触摸事件产生后,它的传递顺序如下:Activity->Window->View

  • onClick会发生的前提是当前View是可点击的,并且它收到了down和up的事件
  • 事件传递过程是由外向内的,事件总是先传递给父元素,然后由父元素分发给子View,通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程,但是ACTION_DOWN事件除外

滑动事件冲突
  • 父容器左右滑动 与子元素上下滑动冲突
  • 父容器与子元素滑动方向相同时滑动冲突
  • 以上场景综合
解决滑动冲突的方法:
1.外部拦截法
重写父容器onInterceptTouchEvent方法
滑动冲突场景: 父容器左右滑动 与子元素上下滑动
可以根据水平方向和竖直方向直接的距离差进行判断 是否需要拦截此滑动事件
@Override
public boolean onInterceptTouchEvent (MotionEvent ev) {
   
switch (ev.getAction()){
       
case MotionEvent. ACTION_MOVE :
           
if ( "父容器需要在onTouchEvent方法里面处理的事件" ){
               
return true;
           
} else {
               
return false;
           
}
           
break;
        default
:
           
break;
   
}
   
return super .onInterceptTouchEvent(ev) ;
}
2.内部拦截法
父容器不拦截除了ACTION_DOWN以外的任何事件
为何不能拦截 ACTION_DOWN事件?因为如果拦截 ACTION_DOWN事件后 事件将不会传递给子元素
@Override
public boolean onInterceptTouchEvent (MotionEvent ev) {
  
if (ev.getAction()==MotionEvent. ACTION_DOWN ){
      
return false;
  
} else {
      
return true;
  
}
}

内部子元素重写 dispatchTouchEvent方法
@Override
public boolean dispatchTouchEvent (MotionEvent ev) {
   
switch (ev.getAction()){
       
case MotionEvent. ACTION_DOWN :
            getParent().requestDisallowInterceptTouchEvent(
true ) ;
            break;
        case
MotionEvent. ACTION_MOVE :
           
if ( "父容器需要在onTouchEvent方法里面处理的事件" ){
                getParent().requestDisallowInterceptTouchEvent(
false ) ; //不干预父类的拦截事件
           
}
           
break;
        case
MotionEvent. ACTION_UP :
           
break;
        default
:
           
break;
   
}
   
return super .dispatchTouchEvent(ev) ;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值