ui事件冲突,取消拦截父控件的事件拦截

   当手指触摸到屏幕时,系统就会调用相应View的onTouchEvent,并传入一系列的action。当有多个层级的View时,在父层级容许的状况下,这个action会一直向下传递直到遇到最深层的View。因此touch事件最早调用的是最底层View的onTouchEvent,若是View的onTouchEvent接收到某个touch action并做了相应处理,最后有两种返回方式return true和return false;return true会告诉系统当前的View须要处理此次的touch事件,之后的系统发出的ACTION_MOVE,ACTION_UP仍是须要继续监听并接收的,并且此次的action已经被处理掉了,父层的View是不可能出发onTouchEvent了。因此每个action最多只能有一个onTouchEvent接口返回true。若是return false,便会通知系统,当前View不关心这一次的touch事件,此时这个action会传向父级,调用父级View的onTouchEvent。可是这一次的touch事件以后发出的任何action,该View都不会再接受,onTouchEvent在这一次的touch事件中不再会触发,也就是说一旦View返回false,那么以后的ACTION_MOVE,ACTION_UP等ACTION就不会在传入这个View,可是下一次touch事件的action仍是会传进来的。
    前面说了底层的View可以接收到此次的事件有一个前提条件:在父层级容许的状况下。假设不改变父层级的dispatch方法,在系统调用底层onTouchEvent以前会先调用父View的onInterceptTouchEvent方法判断,父层View是否是要截获本次touch事件以后的action。若是onInterceptTouchEvent返回了true,那么本次touch事件以后的全部action都不会再向深层的View传递,通通都会传给负层View的onTouchEvent,就是说父层已经截获了此次touch事件,以后的action也没必要询问onInterceptTouchEvent,在此次的touch事件以后发出的action时onInterceptTouchEvent不会再次调用,直到下一次touch事件的来临。若是onInterceptTouchEvent返回false,那么本次action将发送给更深层的View,而且以后的每一次action都会询问父层的onInterceptTouchEvent需不须要截获本次touch事件。只有ViewGroup才有onInterceptTouchEvent方法,由于一个普通的View确定是位于最深层的View,touch事件可以传到这里已是最后一站了,确定会调用View的onTouchEvent。
对于底层的View来讲,有一种方法能够阻止父层的View截获touch事件,就是调用getParent().requestDisallowInterceptTouchEvent(true);方法。一旦底层View收到touch的action后调用这个方法那么父层View就不会再调用onInterceptTouchEvent了,也没法截获之后的action。
用例子总结一下onInterceptTouchEvent和onTouchEvent的调用顺序:
假设最高层View叫OuterLayout,中间层View叫InnerLayout,最底层View叫MyVIew。调用顺序是这样的(假设各个函数返回的都是false)
OuterLayout.onInterceptTouchEvent->InnerLayout.onInterceptTouchEvent->MyView.onTouchEvent->InnerLayout.onTouchEvent->OuterLayout.onTouchEvent。java

@Override    
    public boolean dispatchTouchEvent(MotionEvent ev) {   
        getParent().requestDisallowInterceptTouchEvent(true);  
        return super.dispatchTouchEvent(ev);    
    }

这句话是告诉父view,个人事件本身处理ide

public boolean onTouch(View v, MotionEvent event) {  
     switch (event.getAction()) {  
     case MotionEvent.ACTION_MOVE:   
         pager.requestDisallowInterceptTouchEvent(true);  
         break;  
     case MotionEvent.ACTION_UP:  
     case MotionEvent.ACTION_CANCEL:  
         pager.requestDisallowInterceptTouchEvent(false);  
         break;  
     }  
}

也能够写成相似于上面那样,当用户按下的时候,咱们告诉父组件,不要拦截个人事件(这个时候子组件是能够正常响应事件的),拿起以后就会告诉父组件能够阻止。函数

 

 

还有一个关于子控件和父控件的事件响应问题 
当父控件中有子控件的时候,而且父控件和子空间都有事件处理(好比单击事件)。这时,点击子控件,父控件的单击事件就无效了。spa

好比一个LinearLayout里面有一个子控件TextView,可是TextView的大小没有LinearLayout大code

①若是LinearLayout和TextView都设置了单击事件,那么接口

  • 点击TextView区域的时候,触发的是TextView的事件,
  • 点击TextView之外的区域的时候,仍是触发的LinearLayout的事件。

②若是LinearLayout设置了单击事件,而TextView没有设置单击事件的话,那么事件

  • 无论单击的是TextView区域,仍是TextView之外的区域,都是触发的LinearLayout的单击事件

若是LinearLayout的大小和TextView同样的话,那么get

①若是LinearLayout和TextView都设置了单击事件,那么it

  • 只有TextView的单击事件有效

②若是LinearLayout设置了单击事件,而TextView没有设置单击事件的话,那么io

触发的是LinearLayout的单击事件

相关文章
相关标签/搜索