WebView与ListView滑动冲突——(一)事件基础篇

来源:互联网 发布:mac输入法 u 编辑:程序博客网 时间:2024/06/16 19:41

Android中的事件有很多种,从宏观上来讲我们最常见,最常用的就是onClick事件了,微观上来说就是onTouchEvent、onInterceptTouchEvent、dispatchTouchEvent等方法都具有MotionEvent参数,该Event即为用户一次行为的具体体现。如果其中某一个方法返回true,则代表改方法消费了该事件,则该事件将不会向下传递,其后的ACTION_MOVE、ACTION_UP等事件都将会在这里进行处理,不会向下传递。

MotionEvent 常见事件:

常量 解释 ACTION_DOWN 表示用户开始触摸 ACTION_MOVE 表示用户在移动 ACTION_UP 表示用户抬起了手指 ACTION_CANCEL 表示手势被取消了,不常见 ACTION_OUTSIDE 表示用户触碰超出了正常的UI边界,不常见 ACTION_POINTER_DOWN 有一个非主要的手指按下了(多点按下动作) ACTION_POINTER_UP 一个非主要的手指抬起来了(多点离开动作)

事件分发机制

Android的事件分发机制主要涉及到这三个方法:dispatchTouchEvent、onInterceptTouchEvent以及onTouchEvent

1.dispatchTouchEvent

处理触摸事件的分发,Android中的所有事件都必须经过这个方法的分发,然后决定是自身消费当前事件还是继续往下分发给子控件处理。

2.onInterceptTouchEvent

该方法只有在ViewGroup或其子类中才具有。作用是系统向该ViewGroup及其各个ChildView触发onTouchEvent方法之前对相关事件进行一次拦截。 ACTION_DOWN事件会首先传递到ViewGroup中的onInterceptTouchEvent方法中,下面分两种情况来说明一下该方法返回值的作用。
返回true

  • 如果onInterceptTouchEvent处理完ACTION_DOWN事件返回true,则系统不会将该ACTION_DOWN事件传到目标View中的onTouchEvent方法中,而且后续的ACTION_MOVE、ACTION_UP事件将不再调用该ViewGroup中的onInterceptTouchEvent方法,直接将这些事件传递给该ViewGroup中的onTouchEvent处理。

  • 如果onInterceptTouchEvent处理完ACTION_MOVE返回true,则系统不会将ACTION_MOVE事件传递到目标View中的onTouchEvent方法中,而是传递ACTION_CANCEL事件到目标View的onTouchEvent方法中,只传递一次,此后与目标View没有任何关系(包括最后的ACTION_UP事件),只调用ViewGroup中的onTouchEvent方法。

返回false

  • 如果onInterceptTouchEvent处理完ACTION_DOWN事件返回false,则系统还会将该ACTION_DOWN事件传到目标View当中,并且后续的ACTION_MOVE事件同样先传递到onInterceptTouchEvent中

  • 如果onInterceptTouchEvent处理完ACTION_MOVE返回false,则系统还会将ACTION_MOVE事件传递到目标View中的onTouchEvent方法中。

3.onTouchEvent

对于onTouchEvent也分两种情况来说明把,毕竟这种方法的返回值才是关键。
返回true

  • 如果View中的onTouchEvent返回true的话就表示该View消费了事件,进入不到ViewGroup的onTouchEvent中了

  • 如果ViewGrop的onTouchEvent返回true的话就表示该ViewGrop消费了事件,进入不到activity的onTouchEvent中了

返回false

  • View的onTouchEvent返回为false表示view处理完onTouchEvent后不消费这次事件,那么这个事件就会继续传递到他的上一层ViewGroup的onTouchEvent事件中

  • ViewGrop的onTouchEvent返回为false表示这个ViewGroup处理完onTouchEvent后不消费这次事件,这个事件就会继续传递到activity的onTouchEvent中

这里写图片描述

总之,如果最里层的返回false就会交给他的上一层处理,否则就会消费这次事件,停止向下传递

ViewGroup事件分发模型

想要搞清楚ViewGroup的事件分发机制,首先就得先在脑子中行程一种宏观上的事件模型,才能大致明白事件分发到底是个什么东西。如图:

这里写图片描述

我们就先通过ViewGroup的dispatchTouchEvent来了解一下事件分发模型。当一个Touch事件(触摸事件为例)到达根节点,即Acitivty的ViewGroup时,它会依次下发,下发的过程是调用子View(ViewGroup)的dispatchTouchEvent方法实现的。简单来说,就是ViewGroup遍历它包含着的子View,调用每个View的dispatchTouchEvent方法,而当子View为ViewGroup时,又会通过调用ViwGroup的dispatchTouchEvent方法继续调用其内部的View的dispatchTouchEvent方法。

上述例子中的消息下发顺序是这样的:①-②-③-⑤-⑥-⑦-④。dispatchTouchEvent方法只负责事件的分发,它拥有boolean类型的返回值,当返回为true时,顺序下发会中断。在上述例子中如果⑤的dispatchTouchEvent返回结果为true,那么⑥-⑦-④将都接收不到本次Touch事件。

图解事件分发

看到这相信你已经对事件分发有了大致的了解。下面通过几张图来学习一下dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent这三个方法和MotionEvent是怎么协同工作的。

ACTION_DOWN都未被消费

  • 都不拦截,ACTION_DOWN会依次向下传递
  • 都不消费,onTouchEvent会依次向上传递
  • 后续的ACTION_MOVE和ACTION_UP都不会在被传递
  • dispatchTouchEvent会返回false,表示事件未派发出去(未被消费)

这里写图片描述

ACTION_DOWN被View消费

  • ACTION_DOWN将不会向下传递

这里写图片描述

  • 之前消费了ACTION_DOWN事件,不管我后面消费不消费,ACTION_MOVE和ACTION_UP都会由我来处理(只要不被上层拦截)
  • 如果该View消费了ACTION_MOVE或ACTION_UP,则上层的dispatchTouchEvent将返回true,反之则返回false

这里写图片描述

ACTION_DOWN被View消费,上层拦截剩下事件

  • ACTION_DOWN被View消费后。上层的onInterceptTouchEvent返回true表示拦截事件

这里写图片描述

ACTION_DOWN直接被上层拦截

  • 一开始就被上层ViewGroup所拦截,并且消费了ACTION_DOWN事件,则后面的ACTION_MOVE和ACTION_UP都会被传递给他,不会向下传递给子View

这里写图片描述

注:Android中的Touch事件都是从ACTION_DOWN开始的

  • 单手指操作:ACTION_DOWN—ACTION_MOVE—-ACTION_UP
  • 多手指操作:ACTION_DOWN—ACTION_POINTER_DOWN—ACTION_MOVE–ACTION_POINTER_UP—ACTION_UP
阅读全文
0 0