一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP
当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底 是 ViewGroup来处理Touch事件,还是子view来处理Touch事件呢?这个并不一定。为什么呢?看看下面的调查结果就明白了。
android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:
1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent
2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent
当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由 dispatchTouchEvent 方法进行分发,如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。如果事件传递到某一层的子 view 的 onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。
通过语言描述这个处理逻辑很抽象,下面就用代码来具体说明一下。
layout配置文件 main.xml:
1. <?xml version="1.0" encoding="utf-8"?>
2. <test.lzqdiy.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:orientation="vertical"
4. android:layout_width="fill_parent"
5. android:layout_height="fill_parent"
6. android:gravity="center" >
7. <test.lzqdiy.MyTextView
8. android:layout_width="200px"
9. android:layout_height="200px"
10. android:id="@+id/tv"
11. android:text="lzqdiy"
12. android:textSize="40sp"
13. android:textStyle="bold"
14. android:background="#FFFFFF"
15. android:textColor="#0000FF"/>
16. </test.lzqdiy.MyLinearLayout>
节点层次很简单,一个LinearLayout中添加了一个TextView。
下面是java代码:
1. package test.lzqdiy;
2.
3. import android.app.Activity;
4. import android.os.Bundle;
5.
6. public class TestTouchEventApp extends Activity {
7. /** Called when the activity is first created. */
8. @Override
9. public void onCreate(Bundle savedInstanceState) {
10. super.onCreate(savedInstanceState);
11. setContentView(R.layout.main);
12. }
13. }
14. package test.lzqdiy;
15.
16. import android.content.Context;
17. import android.util.AttributeSet;
18. import android.util.Log;
19. import android.view.MotionEvent;
20. import android.widget.LinearLayout;
21.
22. public class MyLinearLayout extends LinearLayout {
23. private final String TAG = "MyLinearLayout";
24.
25. public MyLinearLayout(Context context, AttributeSet attrs) {
26.
27. super(context, attrs);
28.
29. Log.d(TAG, TAG);
30.
31. }
32.
33. @Override
34. public boolean dispatchTouchEvent(MotionEvent ev) {
35. int action = ev.getAction();
36.
37. switch (action) {
38.
39. case MotionEvent.ACTION_DOWN:
40.
41. Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN");
42.
43. break;
44.
45. case MotionEvent.ACTION_MOVE:
46.
47. Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE");
48.
49. break;
50.
51. case MotionEvent.ACTION_UP:
52.
53. Log.d(TAG, "dispatchTouchEvent action:ACTION_UP");
54.
55. break;
56.
57. case MotionEvent.ACTION_CANCEL:
58.
59. Log.d(TAG, "dispatchTouchEvent action:ACTION_CANCEL");
60.
61. break;
62.
63. }
64. return super.dispatchTouchEvent(ev);
65. }
66.
67. @Override
68. public boolean onInterceptTouchEvent(MotionEvent ev) {
69.
70. int action = ev.getAction();
71.
72. switch (action) {
73.
74. case MotionEvent.ACTION_DOWN:
75.
76. Log.d(TAG, "onInterceptTouchEvent action:ACTION_DOWN");
77.
78. break;
79.
80. case MotionEvent.ACTION_MOVE:
81.
82. Log.d(TAG, "onInterceptTouchEvent action:ACTION_MOVE");
83.
84. break;
85.
86. case MotionEvent.ACTION_UP:
87.
88. Log.d(TAG, "onInterceptTouchEvent action:ACTION_UP");
89.
90. break;
91.
92. case MotionEvent.ACTION_CANCEL:
93.
94. Log.d(TAG, "onInterceptTouchEvent action:ACTION_CANCEL");
95.
96. break;
97.
98. }
99.
100. return false;
101.
102. }
103.
104. @Override
105. public boolean onTouchEvent(MotionEvent ev) {
106.
107. int action = ev.getAction();
108.
109. switch (action) {
110.
111. case MotionEvent.ACTION_DOWN:
112.
113. Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");
114.
115. break;
116.
117. case MotionEvent.ACTION_MOVE:
118.
119. Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");
120.
121. break;
122.
123. case MotionEvent.ACTION_UP:
124.
125. Log.d(TAG, "---onTouchEvent action:ACTION_UP");
126.
127. break;
128.
129. case MotionEvent.ACTION_CANCEL:
130.
131. Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");
132.
133. break;
134.
135. }
136.
137. return true;
138. }
139.
140. }
141.
142. package test.lzqdiy;
143.
144. import android.content.Context;
145. import android.util.AttributeSet;
146. import android.util.Log;
147. import android.view.MotionEvent;
148. import android.widget.TextView;
149.
150. public class MyTextView extends TextView {
151.
152. private final String TAG = "MyTextView";
153.
154. public MyTextView(Context context, AttributeSet attrs) {
155.
156. super(context, attrs);
157.
158. }
159.
160. @Override
161. public boolean dispatchTouchEvent(MotionEvent ev) {
162. int action = ev.getAction();
163.
164. switch (action) {
165.
166. case MotionEvent.ACTION_DOWN:
167.
168. Log.d(TAG, "dispatchTouchEvent action:ACTION_DOWN");
169.
170. break;
171.
172. case MotionEvent.ACTION_MOVE:
173.
174. Log.d(TAG, "dispatchTouchEvent action:ACTION_MOVE");
175.
176. break;
177.
178. case MotionEvent.ACTION_UP:
179.
180. Log.d(TAG, "dispatchTouchEvent action:ACTION_UP");
181.
182. break;
183.
184. case MotionEvent.ACTION_CANCEL:
185.
186. Log.d(TAG, "onTouchEvent action:ACTION_CANCEL");
187.
188. break;
189.
190. }
191. return super.dispatchTouchEvent(ev);
192. }
193.
194. @Override
195. public boolean onTouchEvent(MotionEvent ev) {
196.
197. int action = ev.getAction();
198.
199. switch (action) {
200.
201. case MotionEvent.ACTION_DOWN:
202.
203. Log.d(TAG, "---onTouchEvent action:ACTION_DOWN");
204.
205. break;
206.
207. case MotionEvent.ACTION_MOVE:
208.
209. Log.d(TAG, "---onTouchEvent action:ACTION_MOVE");
210.
211. break;
212.
213. case MotionEvent.ACTION_UP:
214.
215. Log.d(TAG, "---onTouchEvent action:ACTION_UP");
216.
217. break;
218.
219. case MotionEvent.ACTION_CANCEL:
220.
221. Log.d(TAG, "---onTouchEvent action:ACTION_CANCEL");
222.
223. break;
224.
225. }
226.
227. return true;
228.
229. }
230.
231. }
为了指代方便,下面将MyLinearLayout简称为L,将MyTextView简称为 T,L.onInterceptTouchEvent=true 表示的含义为MyLinearLayout中的onInterceptTouchEvent方法返回值为true,通过程序运行时输出的Log来说明调用 时序。
第1种情况 L.onInterceptTouchEvent=false&& L.onTouchEvent=true &&T.onTouchEvent=true 输出下面的Log:
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_DOWN
D/MyTextView(11865): dispatchTouchEvent action:ACTION_DOWN
D/MyTextView(11865): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_MOVE
D/MyTextView(11865): dispatchTouchEvent action:ACTION_MOVE
D/MyTextView(11865): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(11865): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(11865): onInterceptTouchEvent action:ACTION_UP
D/MyTextView(11865): dispatchTouchEvent action:ACTION_UP
D/MyTextView(11865): ---onTouchEvent action:ACTION_UP
结论:TouchEvent完全由TextView处理。
第2种情况 L.onInterceptTouchEvent=false&& L.onTouchEvent=true &&T.onTouchEvent=false 输出下面的Log:
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): onInterceptTouchEvent action:ACTION_DOWN
D/MyTextView(13101): dispatchTouchEvent action:ACTION_DOWN
D/MyTextView(13101): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(13101): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(13101): ---onTouchEvent action:ACTION_UP
结论:TextView只处理了ACTION_DOWN事件,LinearLayout处理了所有的TouchEvent。
第3种情况 L.onInterceptTouchEvent=true&& L.onTouchEvent=true 输出下面的Log:
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): onInterceptTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_MOVE
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_MOVE
...........省略其他的ACTION_MOVE事件Log
D/MyLinearLayout(13334): dispatchTouchEvent action:ACTION_UP
D/MyLinearLayout(13334): ---onTouchEvent action:ACTION_UP
结论:LinearLayout处理了所有的TouchEvent。
第4种情况 L.onInterceptTouchEvent=true&& L.onTouchEvent=false 输出下面的Log:
D/MyLinearLayout(13452): dispatchTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13452): onInterceptTouchEvent action:ACTION_DOWN
D/MyLinearLayout(13452): ---onTouchEvent action:ACTION_DOWN
结论:LinearLayout只处理了ACTION_DOWN事件,那么其他的TouchEvent被谁处理了呢?答案是LinearLayout最外层的Activity处理了TouchEvent。
资源下载:http://download.csdn.net/detail/u012264122/7794911