1.Android的事件有哪些?
onClick, onScroll, onFling等等,都是由许多个Touch组成的
2.Touch的第一个状态是什么顺序?
第一个状态肯定是 ACTION_DOWN, 表示按下了屏幕。之后,touch将会有后续事件,可能是: ACTION_MOVE //表示为移动手势 ACTION_UP //表示为离开屏幕 ACTION_CANCEL //表示取消手势,不会由用户产生,而是由程序产生的 一个Action_DOWN, n个ACTION_MOVE, 1个ACTION_UP,就构成了Android中众多的事件。
3.ViewGroup类的控件嵌套时事件如何传递和处理?
android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:
1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent
2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent
4.onInterceptTouchEvent()方法用来做什么?
对于ViewGroup类的控件,有一个很重要的方法,就是onInterceptTouchEvent(),用于处理事件并改变事件的传递方向,它的返回值是一个布尔值,决定了Touch事件是否要向它包含的子View继续传递,这个方法是从父View向子View传递。
5.onTouchEvent()方法用来做什么?
onTouchEvent(),用于接收事件并处理,它的返回值也是一个布尔值,决定了事件及后续事件是否继续向上传递,这个方法是从子View向父View传递
6.dispatchTouchEvent是负责分发事件
7.整个过程是怎么样的?
dispatchTouchEvent是负责分发事件的,事件从 activity 传递出来之后,最先到达的就是最顶层 view 的 dispatchTouchEvent ,然后它进行分发,如果返回false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的dispatchTouchEvent 再来开始这个事件的分发。
8.注意看我的例子是怎么重写的?必须调用surper方法,并且注意返回值
9.一个例子:要求最上层view先处理触摸事件,当最上层view不需要处理时,让子view来处理
需求:要做一个完全通过flip手势来切换的界面。在最上层用一个ViewFlipper作为容器,并检测flip手势操作。
难题:ViewFlipper的flip手势检测需要的MotionEvent,会被各种子View的触摸检测给拦截了。比如界面上有一个Button,则当手指按下Button(还没有抬起)然后flip出Button,最上层的flip手势检测是无效的。
原因:android对Touch Event的分发逻辑是View从上层分发到下层(dispatchTouchEvent函数),然后下层优先开始处理Event(先mOnTouchListener,再onTouchEvent)并向上返回处理情况(boolean值),下层若返回true,则上层不再处理。
于是我们首先想到,要保证flip手势检测,需要把所有的Touch Event都传到上层去。
然而在分发逻辑之外还有一个逻辑,android估计是为了保证每个触操作只能由一个View来进行完整响应,对ACTION_DOWN事件有个额外的逻辑:如果某个View在处理ACTION_DOWN事件时返回false(即该View未处理此事件),那么后续产生的其它事件将直接忽略掉这个View(不过LongPress又有另外的独立逻辑)。举例来说就是,如果你处理ACTION_DOWN时返回了false,那么你这个View将得不到ACTION_MOVE或ACTION_DOWN等等这些后续事件了。
于是难题出现了,你若把Touch Event都想办法给传到上层了(只能通过返回false来传到上层),那么下层的各种子View就不能处理后续事件了。
解决方案:
开始仅着眼于Touch Event处理完后的回传过程,想了N久不得,毕竟我想实现的是一个需要打破android事件处理逻辑的效果(就是一个连续性操作,只有不满足上层要求时,才轮到下层处理)。然后突然想到事件的分发过程,便豁然开朗:
覆写最上层的View的dispatchTouchEvent函数,代码如下:
@Override public boolean dispatchTouchEvent(MotionEvent event) {
if (_flipDetector.onTouchEvent(event)) { event.setAction(MotionEvent.ACTION_CANCEL); }
return super.dispatchTouchEvent(event); }
_flipDetector.onTouchEvent(event)这个可以根据需要返回值。
于是效果实现。也就是在分发之前便进行手势检测处理,若检测成功,则取消下层的一切处理过程。
参考两篇比较好的文章
1.http://blog.csdn.net/starfeng11/article/details/7009338
2.http://blog.csdn.net/spt110/article/details/7919870
自己做测试的例子:
http://download.csdn.net/detail/fastthinking/7089909