先来看一个例子
在一个界面上有一个按钮1,现在在按钮1上覆盖一个按钮2,然后点击按钮2,请问底下的按钮1能拿到点击事件吗?
要搞懂这个问题,首先我们必须对安卓的事件分发机制有一个基本的了解,接下来我用3W1H的方式说明:

- 分发:表示事件未找到消费地点,将交给自身的下一函数处理;拦截:表示事件不再传递给子类;消费:表示事件找到消费地点,事件传递完结
- 从图上我们可以知道,安卓的事件分发机制其实就容器和控件通过分发和拦截,沿着视图树向下传递触摸事件,当到达底层控件或者被拦截时,表示事件不在线下分发,继而沿着视图树向上寻找真正消费的地方的过程。
在回来看看之前的例子,它的视图树应该是这样的:

分析
- 从图中我们可以看到Button2和Button1是并列关系,而且Button2优先于Button1
- 问题问的是button1是否会拿到触摸事件,Button本身已经是最小的单位了,这里分析就是View中事件传递的问题
- 事件传递中View拥有dispatchTouchEvent和onTouchEvent两个方法,即分发和消费。
- 这里的Button是原生的控件并未人为干扰,View控件的事件触发顺序是先执行onTouch方法,在最后执行onClick方法,如果onTouch返回true,则不会调用onClick方法。 onTouch和onTouchEvent以及onClick的顺序,有什么区别,又该如何使用?
当用户点击Button2时候,事件会这么传递:

因此我们可以知道,如果点击了Buttn2,点击事件会在Button2的onClick事件中消费掉,Button1是拿不到点击事件的,也拿不到任何触摸事件,除非在Button2中重写了分发方法,不走super方法,直接返回true,那么Button1中将拿到触摸事件。

-END-
网友评论