对于移动端来说,用户和应用的交互方式主要就是触摸(包括点击,滑动等)
那么首先就从用户触摸的对象不同作为切入点,Android中有两种视图(View),分别是View和ViewGroup,其中View是ViewGroup的父类。View和ViewGroup的最大区别就在于ViewGroup是存在子View的,也就是因为这一点,才出现了今天讨论的重点,触摸事件是如何传递的。
整个触摸分发过程可以简化成三个主要的方法:
boolean dispatchTouchEvent() //触摸事件分发方法
boolean onInterceptTouchEvent() //触摸事件拦截方法
boolean onTouchEvent() //触摸事件处理方法
dispatchTouchEvent
首先看看这个方法,这个方法的作用就是将触摸事件(按下,抬起,移动)向自己的子View进行传递。
当方法返回值为true时,View或ViewGroup触摸事件传递给同样被触摸的下层View
当方法返回值为false时,View或ViewGroup触摸事件将不会传递给它的下层View,至于ViewGroup本身是否处理这个触摸事件,需要根据该View或ViewGroup的onTouchEvent()方法返回值判断。
onInterceptTouchEvent
触摸事件拦截方法,这个方法是ViewGroup所专属的,也就是说View并没有拦截方法
当方法返回值为true时,ViewGroup会将触摸事件直接拦截,之后交给onTouchEvnet()方法,决定是否自己处理。
当方法返回值为false是,ViewGroup不会拦截事件,触摸事件就会向下层继续传递
onTouchEvent
触摸事件处理方法,由该方法来对触摸事件进行处理。
当返回值为true时,表示消耗本次触摸事件,并结束本次事件分发传递。
当返回值为false时,表示不消耗本次触摸事件。
注意消耗这个词,我觉得这个形容方式很贴切,如果最下层的View或是ViewGroup的返回值为false,那么本次事件分发只执行了一半,之后本次的触摸事件会从下层按原先分发路径反向传回,这时如果之前有View或是ViewGroup做了onTouch()处理,那么就会将触摸事件消耗,如果反向传递依然没有View进行处理,那么本次事件传递就定为失效。
又到了举个栗子的时间了:
模拟场景:这是一个ViewGroup中包含了一个ViewGroup,左View盖在右View的上方,形成的一个结构图。
/**写了一大块文字又给删了,觉得咱们还是用伪代码表示比较好理解**/
//首先,第一个ViewGroup为VG1,第二个ViewGroup为VG2,左侧的View为V1,右侧的View为V2
//用户进行了触摸,以上控件都在触摸范围内
//以下代码都只是做思路分析,与真实代码完全不同,提醒各位看官不要误会
if(VG1.dispatchTouchEvent){ //VG1分发为true
if(VG1.onInterceptTouchEvent){
}
}else{ //分发为false
}
1、一号ViewGroup获取触摸事件,dispatchTouchEvent返回值为true,事件准备向二号ViewGroup分发(跳至3/4)
2、一号ViewGroup获取触摸事件,dispathcTouchEvent返回值为false,事件不准备不向下分发(跳至5)
3、一号ViewGroup的onInterceptTouchEvent返回值为true,一号ViewGroup自行拦截,交给onTouch处理
4、一号ViewGroup的onInterceptTouchEvent返回值为false,一号ViewGroup不拦截,向下分发触摸事件
5、一号ViewGroup的onInterceptTouchEvent返回值为false,一号ViewGroup不拦截,本次触摸事件结束
以上就是针对顶层ViewGroup的触摸事件分析,完整分析整个触摸事件实在有太多种情况,所以主要是掌握方法,依次类推就能知道指定消费触摸事件要怎样处理整个布局结构内的各个方法了。