开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。
android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法:
1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent
2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent
注意:不是所有的View的子类,很多教程都说的是所有的View的子类,只有可以向里面添加View的控件才需要分发,比如TextView它本身就是最小的view了,所以不用再向它的子视图分发了,它也没有子视图了,所以它没有dispatch和Intercept,只有touchEvent。
首先我们看一下我的测试的界面:
<ignore_js_op style="word-wrap: break-word;">
<ignore_js_op style="word-wrap: break-word;">
说明: 白色为最外层,它占满整个屏幕;
红色为中间区域,属于白色中的一层;
黑色为中心区域,必于红色中的一层。
注意:他们本质上是:LinearLayout,而不是RelativeLayout或者其它布局。
1.由中心区域处理touch事件
布局文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <com.kris.touch.widget.TouchView
- android:id="@+id/view_out"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#fff"
- android:gravity="center">
- <com.kris.touch.widget.TouchView
- android:id="@+id/view_mid"
- android:layout_width="300px"
- android:layout_height="400px"
- android:background="#f00"
- android:gravity="center">
- <com.kris.touch.widget.TouchView
- android:id="@+id/view_center"
- android:layout_width="150px"
- android:layout_height="150px"
- android:background="#000"
- android:gravity="center"
- android:clickable="true">
- </com.kris.touch.widget.TouchView>
- </com.kris.touch.widget.TouchView>
- </com.kris.touch.widget.TouchView>
- </LinearLayout>
复制代码
注意: android:clickable="true"
接下来我们看一下打印的日志:
<ignore_js_op style="word-wrap: break-word;">
<ignore_js_op style="word-wrap: break-word;">
结合是上面的日志,我们可以看一下ACTION_DOWN事件处理流程:
<ignore_js_op style="word-wrap: break-word;">
<ignore_js_op style="word-wrap: break-word;">
说明:
首先触摸事件发生时(ACTION_DOWN),由系统调用Activity的dispatchTouchEvent方法,分发该事件。根据触摸事件的坐标,将此事件传递给out的dispatchTouchEvent处理,out则调用onInterceptTouchEvent 判断事件是由自己处理,还是继续分发给子View。此处由于out不处理Touch事件,故根据事件发生坐标,将事件传递给out的直接子View(即middle)。
Middle及Center中事件处理过程同上。但是由于Center组件是clickable 表示其能处理Touch事件,故center中的onInterceptTouchEvent方法将事件传递给center自己的onTouchEvent方法处理。至此,此Touch事件已被处理,不继续进行传递。
2.没有指定谁会处理touch事件
布局文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <com.kris.touch.widget.TouchView
- android:id="@+id/view_out"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#fff"
- android:gravity="center">
- <com.kris.touch.widget.TouchView
- android:id="@+id/view_mid"
- android:layout_width="300px"
- android:layout_height="400px"
- android:background="#f00"
- android:gravity="center">
- <com.kris.touch.widget.TouchView
- android:id="@+id/view_center"
- android:layout_width="150px"
- android:layout_height="150px"
- android:background="#000"
- android:gravity="center">
- </com.kris.touch.widget.TouchView>
- </com.kris.touch.widget.TouchView>
- </com.kris.touch.widget.TouchView>
- </LinearLayout>
复制代码
注意:只是比上一次的布局少了android:clickable="true"
接下来我们看一下打印的日志
<ignore_js_op style="word-wrap: break-word;">
<ignore_js_op style="word-wrap: break-word;">
结合是上面的日志,我们可以看一下ACTION_DOWN事件处理流程:
<ignore_js_op style="word-wrap: break-word;">
说明:
事件处理流程大致同上,区别是此状态下,所有组件都不会处理事件,事件并不会被center的onTouchEvent方法“消费”,则事件会层层逆向传递回到Activity,若Activity也不对此事件进行处理,此事件相当于消失了(无效果)。
对于后续的move、up事件,由于第一个down事件已经确定由Activity处理事件,故up事有由Activity的dispatchTouchEvent直接分发给自己的onTouchEvent方法处理。
代码请看最后的附件
总结:
1) Touchevent 中,返回值是 true ,则说明消耗掉了这个事件,返回值是 false ,则没有消耗掉,会继续传递下去,这个是最基本的。2) 事件传递的两种方式:
隧道方式:从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递。
冒泡方式:从最内层子元素依次往外传递直到根元素或在中间某一元素中由于某一条件停止传递。 android对Touch Event的分发逻辑是View从上层分发到下层(dispatchTouchEvent函数)类似于隧道方式,然后下层优先开始处理Event(先mOnTouchListener,再onTouchEvent)并向上返回处理情况(boolean值),若返回true,则上层不再处理。类似于冒泡方式
于是难题出现了,你若把Touch Event都想办法给传到上层了(只能通过返回false来传到上层),那么下层的各种子View就不能处理后续事件了。而有的时候我们需要在下层和上层都处理Touch事件
举个例子,ViewFlipper用来检测手势,在内部我们放几个Image,有点像gallery的效果,也就是左右滑动切换图片,但是图片有时候我们希望可以放大缩小!这样就会存在ViewFlipper里面需要touch事件,而在image里面也需要一个touch事件(当图片大小屏幕边界的时候可以拖动图片,而不是左右切换图片)。
我首先的思路是着手于事件回传的方式,研究了n久,实际了n久,都没达到自己想要的结果 ,我甚至于把gallery和gallery3D 的源码下载下来看了N久也没办法去解决,在这里随便说一下gallery吧,gallery虽然在这个效果,但是人家并不是ViewFlipper加image这样来实现的,人家是像游戏这样用一个view来统一处理的,我们可以简单的理解成自定义了一个控件,这样touch事件想怎么处理就怎么处理,不过就是逻辑复杂了,我们想偷懒就没办法了,呵呵。。。
最后不停的试啊试啊,想到一个可行的方案,但是我觉得不是很靠谱,也就是:我们在ViewFlipper这里,我们先把所有的touch都截取到,然后在他的onTouchEvent中,我们先调用imageview的onTouchEvent事件,如果返回true,证明这个事件,imageview要用,那么ViewFlipper就当什么事都没发生,如果imageview返回的false,则调用自己的touchEvent.伪代码如下:
- //自定义一个MyViewFlipper 继承于ViewFlipper,并且实现onTouchEvent方式,
复制代码
我觉得他不靠谱的原因为: 1. 他打断了android的原有的机制,不是很提倡。
2. 得试先知道ViewFlipper里面的控件,或者说通过某种路径能获取到
3. 如果ViewFlipper里面的控件多了,就蛋疼了
好了,如果有什么意见或者建议,大家一起讨论。
上demo:
(注意:不是ViewFlipper的哈,只是上面touch事件打印的demo,你们下载后可以自己尝试一下,这样能加深印象,我相信比我说的更有说服力)
(ViewFlipper的代码是公司的项目里面的 ,虽然实现了,但是我还是把它给干掉了,像上面说的,我觉得不靠谱,呵呵,纯属个人习惯问题)
相关推荐
本文将深入解析Android的Touch事件传递机制,并结合源码进行详细阐述。 首先,Android的触摸事件主要包括ACTION_DOWN、ACTION_UP、ACTION_MOVE、ACTION_CANCEL和ACTION_POINTER_DOWN/UP等几种类型。当用户触摸屏幕...
touch机制好好看了一下,呵呵。。android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法:1)publicbooleandispatchTouchEvent(MotionEvent ev)这个方法用来分发TouchEvent2)...
本文将深入解析Android的Touch事件分发机制,并通过一个名为"EventDispatchTest"的示例来说明。 1. **事件分发流程** Android中的触摸事件分发分为三个阶段:`dispatchTouchEvent()`, `onInterceptTouchEvent()`, ...
本文将深入探讨Android事件传递机制,并结合提供的"TestTouch"测试代码进行解析。 Android事件传递机制主要围绕着触摸事件(MotionEvent)展开,当用户在屏幕上进行点击、滑动等操作时,这些动作会转化为一系列的...
本Demo主要展示了Android的Touch事件分发机制,包括事件的传递顺序、处理流程以及如何自定义控件来拦截或消费事件。下面将详细解析这些知识点。 1. **事件流**: Android的Touch事件流分为三个阶段:**ACTION_DOWN...
通过上述分析可以看出,Android的触摸事件分发机制非常灵活且强大,能够根据实际需求在不同的视图之间传递事件。关键在于 `ViewGroup` 的 `onInterceptTouchEvent` 方法和 `View` 的 `onTouchEvent` 方法的选择性...
Android Input 事件获取机制 Android 操作系统中,input 事件是指用户与设备交互...本文详细介绍了 Input System 的启动流程、事件简介、事件读取流程等内容,希望能够帮助读者更好地理解 Android 的 Input 事件机制。
本文将详细解析Android事件分发机制的第三部分:事件分发和消费,帮助开发者深入理解这一关键过程。 事件分发主要包括两个阶段:事件传播和事件消费。当用户在屏幕上进行触摸操作时,Android会生成一个MotionEvent...
本篇将深入解析“android Touch触发事件的生命周期”,着重讨论ViewGroup中点击事件的`dispatchTouchEvent()`, `onInterceptTouchEvent()`, 和`onTouchEvent()`这三个关键方法之间的关系及其工作流程。 首先,我们...
4. **与Android Media框架集成**:在Android应用中,通常需要将处理后的音频数据传递给`AudioTrack`或`MediaPlayer`进行播放。 **四、学习与实践** 1. **调试与优化**:开发者可以通过日志输出来检查处理过程中的...
本文将深入探讨Android Touch系统的工作原理,包括触摸事件的产生、传递和处理流程,以及关键类和方法的解析。 1. 触摸事件的生命周期 当用户在屏幕上触摸时,事件首先由硬件层的触控传感器捕捉,然后转换为...
在Android系统中,触摸事件(Touch Event)是用户与设备交互的重要方式,它涉及一系列复杂的分发机制。本文将深入解析Android Touch事件的分发过程,帮助开发者更好地理解和设计应用程序。 1. 触摸事件的生命周期 ...
【Touch事件分发】在Android系统中,触摸事件(Touch事件)是用户与屏幕交互的主要方式,涉及到Activity、View和ViewGroup之间的事件传递。本文将深入解析Android中的触摸事件分发机制,帮助开发者理解并更好地处理...
### Android O 多屏Touch方案解析 随着移动设备技术的发展,多屏显示逐渐成为一种新的交互方式,特别是在汽车信息系统中,这种技术的应用越来越广泛。在Android O系统中,实现了一个多屏Touch方案,并且已经在实际...
这份资料深入解析了 Android 的触控系统,包括事件分发、触摸事件处理以及如何优化用户体验。下面将详细阐述其中的关键知识点。 一、Android 触控系统基础 Android 触控系统是移动应用开发中的核心部分,它负责处理...
在Android开发中,触摸事件(Touch Event)是用户与设备交互的重要方式,它涉及到一系列复杂的事件分发机制。本文将详细解析`android touchevent`的相关知识点,通过一个实际的Demo来阐述`ontouchevent`事件处理以及...
`TouchEventSample`是一个典型的Android项目,它详细展示了如何处理和解析Android系统的触摸事件。该项目主要关注Java语言,因为这是Android开发的主要编程语言。 在Android中,触摸事件通过MotionEvent类进行传递...