View的事件分发机制

来源:互联网 发布:数据库课程设计mysql 编辑:程序博客网 时间:2024/05/16 01:07
1.点击事件的传递规则
     点击事件的分发过程是由三个很重要的方法来共同完成
@Override
public booleandispatchTouchEvent(MotionEvent ev) {
   
return super.dispatchTouchEvent(ev);
}

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

@Override
public booleanonTouchEvent(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 booleanonInterceptTouchEvent(MotionEvent ev) {
   
switch(ev.getAction()){
       
caseMotionEvent.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 booleanonInterceptTouchEvent(MotionEvent ev) {
  
if(ev.getAction()==MotionEvent.ACTION_DOWN){
      
return false;
  
}else{
      
return true;
  
}
}

内部子元素重写dispatchTouchEvent方法
@Override
public booleandispatchTouchEvent(MotionEvent ev) {
   
switch(ev.getAction()){
       
caseMotionEvent.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 0
原创粉丝点击