View负责android应用的显示,有很重要的地位,而理解View的事件分发机制是实现高质量自定义View和解决滑动冲突问题的基础,既是重点,也是难点。 本文首先介绍View事件分发机制的流程,然后总结出View事件分发机制的一些结论,最后分析源码知道这些结论是怎么总结来的。
所谓点击事件的事件分发,其实就是对MotionEvent事件的分发过程。当手指点击屏幕时,就会产生一个MotionEvent,然后系统需要把这个事件传递给一个具体的View,这个传递的过程,就是事件分发。 事件分发流程: 首先,系统会将事件分发给Activity的dispatchTouchEvent(ev)
方法,在dispatchTouchEvent(ev)
方法中,默认实现下,Activity会把事件分发给Window,Window再把事件分发给DectorView,DectorView接着把事件分发给顶层View,顶层View接着把事件分发给各级子View。如果有View消费了事件,dispatchTouchEvent(ev)
会返回true并返回,表示已消费了事件。如果没有View消费事件,dispatchTouchEvent(ev)
方法会把事件传递给Activity的onTouchEvent(ev)
方法。如果重写dispatchTouchEvent(ev)
方法并返回true或false,事件就不再传递给Window及各级View,而直接在Activity的dispatchTouchEvent(ev)
中消费。 如果事件传递给了ViewGroup,就会调用它的dispatchTouchEvent(ev)
方法。默认实现下,它会询问自身的onInterceptTouchEvent(ev)
方法是否拦截事件。如果拦截,首先,它会查看是否设置有touchListener,如果设置有,就调用onTouch(ev)
方法,如果onTouch(ev)
方法返回true,表示已消费事件,它就返回true,表示事件已在本ViewGroup消费,如果onTouch(ev)
方法返回false,它就调用自身的onTouchEvent(ev)
方法消费事件。如果不拦截,它就把事件传递给子View的dispatchTouchEvent(ev)
方法。如果重写dispatchTouchEvent(ev)
并返回true,表示直接在这个方法中消费事件,事件不再传递。如果重写并返回false,表示不在本View及子View中消费事件,事件会返回给上级,一般情况下,上级会在dispatchTouchEvent(ev)
方法中把事件传递给onTouchEvent(ev)
处理。 如果事件传递给了View,就会调用它的dispatchTouchEvent(ev)
方法。默认情况下,它会查看是否设置有touchListener,如果设置有,就调用onTouch(ev)
方法,之后与ViewGroup相同,如果onTouch(ev)
返回true,就不调用onTouchEvent
,如果返回false,就调用。如果重写dispatchTouchEvent(ev)
并返回true,表示直接在这个方法中消费事件,事件不再传递。如果重写并返回false,表示不在本View中消费事件,事件会返回给上级,一般情况下,上级会在dispatchTouchEvent(ev)
方法中把事件传递给onTouchEvent(ev)
处理。 当事件传递给View或ViewGroup的onTouchEvent时,如果返回true,表示事件在这里消费,事件停止传递,如果返回false或super,表示事件不在这里消费,事件会被返回给上级处理。super中的默认实现会在ACTION_UP事件发生时会调用performClick,在这个方法中会检查是否设置有点击事件监听器,如果设置有,就会调用onClick事件。 事件分发流程图如下:
新闻热点
疑难解答