点击事件分发流程如下:
1.当我我们点击屏幕时,触发Activity的dispatchTouchEvent()方法,如果它返回true或者false则代表事件被消费(不再传递),返回super()时则会传到ViewGroup的dispatchTouchEvent()方法。
2.当ViewGroup的dispatchTouchEvent()方法返回true时,代表事件被消费。如果返回false则会把该事件返回到Activity的onTouchEvent()方法进行处理,返回super()则事件传递到ViewGroup的onInterceptTouchEvent()方法,onInterceptTouchEvent()返回true代表拦截该事件,则把事件交给ViewGroup的onTouchEvent()方法处理,如果它返回的是false或者super(),则代表不拦截该事件,所以事件会传递到View的dispatchTouchEvent()
3.当view的dispatchTouchEvent()返回true时同样代表事件被消费,返回false则事件会传递到ViewGroup的onTouchEvent(),返回super()事件传递到View的onTouchEvent()方法,onTouchEvent()返回ture代表事件被消费,返回false则事件传递回上一层的onTouchEvent();
自定义一个viewGroup
自定义一个view
在布局文件中viewGroup包含view
activity和view重写dispatchTouchEvent()和onTouchEvent(),viewGroup重写dispatchTouchEvent()和onInterceptTouchEvent()和onTouchEvent(),每个方法都打上log,返回值都是默认的。
UI效果如下:
1.当我点击View的时候log输出是这样的:
红色框代表点击事件的分发路径,黑色框代表触摸事件的分发路径(因为一般点击事件后面都会带有一个以上的触摸事件):
我们看到点击事件的分发路径是一个U字形,事件一路从activity传下来到view,然后view再一路传回去。最后在Activity的onTouchEvent()方法中消费。
而黑色框代表点击事件后伴随的触摸事件,它由Activity的dispatchTouchEvent()触发后直接到onTouchEvent();
为什么会这样呢,为什么它不像点击事件一样走完所有流程呢????这个后面我们会来讲解,因为触摸事件跟点击事件的消费有关
2.当我们修改View的onTouchEvent()返回值==true时,Log日志是这样的:
点击事件一路分发下来,到view的onTouchEvent()停止传递,事件被消费。然后再来看触摸事件,分发路径是一样。
3.当我们修改ViewGroup的onInterceptTouchEvent()和onTouchEvent()返回值为true时,Log日志:
ViewGrounp的onInterceptTouchEvent()和onTouchEvent()返回值为true时,代表拦截事件,并在自身的onTouchEvent()中消费,所以onInterceptTouchEvent()==true时代表拦截,点击事件不会向下传递,而是交到了自身的onTouchEvent(),黑色框代表后续的触摸事件,我们看到它走到ViewGroup的dispatchTouchEvent()后直接转到onTouchEvent()。为什么和第一个例子不一样了?
4.当ViewGroup的onTouchEvent()返回值为true,其他方法都是默认时,日志如下:
因为viewGroup的onInterceptTouchEvent()默认是不拦截的,所以点击事件一路从activity分发到view,view没有进行消费,最后事件由view返回到viewGroup的onTouchEvent(),然后停止消费。
触摸事件从activity分发到viewGroup的dispatchTouchEvent()后也是直接转到onTouchEvent(),分发路径和上面的第三个例子一样。
点击事件对于dispatchTouchEvent()方法:
1.return true:消费掉事件,终止传递。
2.return false: 将事件传递给上一级View的onTouchEvent()方法。如果是Activity的dispatchTouchEvent()方法,则也是消费掉事件,终止传递。
3.return super:如果是Activity,则传给下一级view(viewGroup)的dispatchTouchEvent;如果是ViewGroup,则传给自己的onInterceptTouchEvent();如果是View,则传给自己的onTouchEvent().
点击事件对于onInterceptTouchEvent()方法:
1.return true:将事件传递给ViewGroup自己的onTouchEvent()方法处理。
2.return false/super:将事件传递给下一级View的dispatchTouchEvent()。
3.onInterceptTouchEvent()方法是viewGrounp特有的
点击事件对于onTouchEvent()方法:
1.return true:消费掉事件,终止传递。
2.return false/super:将事件传递给上一级view的onTouchEvent()方法。
3.Activity的onTouchEvent()方法不管返回什么都会终止事件
触摸事件:
1.由例子1得出:点击事件在activity中的方法被消费,触摸事件也会被在activity中消费,并且不会走点击事件的分发流程,而是直接抄近路。
2.点击事件是在viewGroup中的方法被消费,那么触摸事件也会被在viewGroup中消费,并且会跳过viewGroup的onInterceptTouchEvent()方法,像例子3、4,虽然点击事件的分发路径不一样,但是最后都是在viewGroup的onTouchEvent()消费,因此他们的触摸事件也是在onTouchEvent()消费,并且也是抄近路。
3.点击事件是在view中的方法被消费,那么触摸事件在view中消费,分发路径和点击事件一样
一直网上看了很多篇文章,写的都不是很好,特别是画图画的云里雾里,看都看不懂。最后发现掘金有篇文章写的不错: