Android事件分发机制研究

来源:互联网 发布:redis和mysql结合使用 编辑:程序博客网 时间:2024/04/30 14:45

一直对android的事件分发机制很困惑的,最近又重新看了下这块的知识,配合自己写个小demo,打log研究了下,做个读书笔记,备忘,如有错误,欢迎批评指正。

  • 结论一:
    如果在父容器中这样写:
@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return true;}

onInterceptTouchEvent表示是否拦截触摸事件,如果返回true,则其内的子控件的触摸事件,onClick事件都执行不到了。但可通过ViewGroup的requestDisallowInterceptTouchEvent方法干预父控件的事件分发,具体如何干预,未测试。

  • 结论二:
    如果一个触摸事件传递到一个控件上,它的dispatchTouchEvent会被调用,如果在父控件的onInterceptTouchEvent返回false的前提下,子控件dispatchTouchEvent返回true,代表该子控件自己消费到该触摸事件(onTouchListener会被执行,如果有的话),即触摸事件不会被父控件处理,父控件的onTouchListener和onTouchEvent方法都走不到。
  • 结论三:
    触摸事件的分发是从上往下分发的,Activity->Window->View.在View之间也是是从上往下分发的,触摸事件先到达父容器,然后父容器再下发给子View.所以响应触摸事件去执行事情的顺序就反过来了,从子View开始处理起,如果子view的dispatchTouchEvent方法返回了false,则就传递给父容器处理(父容器的onTouchListener会被调到)。注意此时子view的onTouchListener和onTouchEvent(如果onTouchListener返回false)事件依然会被调到,只是调完后给父控件接着调用,如果父容器的dispatchTouchEvent方法也返回了false,则事件继续往上传递,如果dispatchTouchEvent都返回了,false,则Activity的onTouchEvent会被掉到。
  • 结论四:
    onTouchListener方法在事件分发过程中的优先级最高,如果一个view设置了onTouchListener方法且返回了true,代表事件已被消费,则他的onTouchEvent方法就走不到了。
    注意:我看任大神的书上说如果子View的onTouchEvent方法返回false,则父容器的触摸事件会被调的,而我测下来,不是这样,将子View的onTouchEvent返回了fasle,此时查看子view的dispatchTouchEvent的默认返回值也为false,此时事件确实传到父容器里面调用去了,但如果此时我把子View的diapatchTouchEvent方法强制返回true,(不是默认的返回super.dispatchTouchEvent,而是先是调用super.dispatchTouchEvent,然后返回true),此时即使onTouchEvent返回了false,父控件的触摸和点击事件都没有调到。

所以感觉onTouchEvent返回false父容器的触摸事件会被掉到不准确,应该是dispatchTouchEvent返回false,父容器的触摸事件才会被掉到。不管onTouchEvent返回true or false,只要dispatchTouchEvent返回false,父容器的触摸事件就会被调到。

我的测试demo地址放到github上去了,有需要的可以下载试下,很例子粗糙,仅作测试所用。地址:https://github.com/happycodinggirl/TestTouchEvent
本文文章如有不对的地方,还望指出。

0 0