Android Touch事件传递机制解析

举报
ShaderJoy 发表于 2021/12/30 01:49:38 2021/12/30
【摘要】 Android Touch事件传递机制解析 android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEvent ev)  这个方法用来分发TouchEvent ...
Android Touch事件传递机制解析
android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:
1public boolean dispatchTouchEvent(MotionEvent ev)  这个方法用来分发TouchEvent
2public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent
测试程序界面
下述3Layout包含关系见如下界面图。
1.jpg 
2012-4-25 19:12 上传
下载附件 (20 KB)



状态1:由center处理Touch事件


  
  1. Xml如下:
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:orientation="vertical" >
  7. <dk.touch.MyLayout
  8. android:id="@+id/out"
  9. android:layout_width="fill_parent"
  10. android:layout_height="fill_parent"
  11. android:gravity="center"
  12. android:background="#ff345600"
  13. >
  14. <dk.touch.MyLayout
  15. android:id="@+id/middle"
  16. android:layout_width="200dp"
  17. android:layout_height="200dp"
  18. android:gravity="center"
  19. android:background="#ff885678"
  20. >
  21. <dk.touch.MyLayout
  22. android:id="@+id/center"
  23. android:layout_width="50dp"
  24. android:layout_height="50dp"
  25. android:background="#ff345678"
  26. android:focusable="true"
  27. android:focusableInTouchMode="true"
  28. android:clickable="true"
  29. >
  30. </dk.touch.MyLayout>
  31. </dk.touch.MyLayout>
  32. </dk.touch.MyLayout>
  33. </LinearLayout>
  34. 注意:只有center这个部分是会处理/消费 Touch事件。
2.png

事件传递记录结果如上图。
由于DownMoveUp事件处理流程略微不同,故分开分析。
ACTION_DOWN事件处理流程:
3.png
首先触摸事件发生时(ACTION_DOWN),由系统调用ActivitydispatchTouchEvent方法,分发该事件。根据触摸事件的坐标,将此事件传递给outdispatchTouchEvent处理,out则调用onInterceptTouchEvent 判断事件是由自己处理,还是继续分发给子View。此处由于out不处理Touch事件,故根据事件发生坐标,将事件传递给out的直接子View(即middle)。
MiddleCenter中事件处理过程同上。但是由于Center组件是clickable 表示其能处理Touch事件,故center中的onInterceptTouchEvent方法将事件传递给center自己的onTouchEvent方法处理。至此,此Touch事件已被处理,不继续进行传递。
Move和 up 事件处理流程类似,但是再center内的dispatchTouchEvent方法内被直接分配给onTouchEvent处理,不需经过onInterceptTouchEvent判断。这是由于,android系统中将1down事件、nmove事件、1up事件整体作为一次逻辑上的触控操作,Down事件已经确定了处理事件的对象,则后续的moveup事件也确定了处理事件的对象。
状态2:都不处理事件


  
  1. Xml如下:
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:orientation="vertical" >
  7. <dk.touch.MyLayout
  8. android:id="@+id/out"
  9. android:layout_width="fill_parent"
  10. android:layout_height="fill_parent"
  11. android:gravity="center"
  12. android:background="#ff345600"
  13. >
  14. <dk.touch.MyLayout
  15. android:id="@+id/middle"
  16. android:layout_width="200dp"
  17. android:layout_height="200dp"
  18. android:gravity="center"
  19. android:background="#ff885678"
  20. >
  21. <dk.touch.MyLayout
  22. android:id="@+id/center"
  23. android:layout_width="50dp"
  24. android:layout_height="50dp"
  25. android:background="#ff345678"
  26. >
  27. </dk.touch.MyLayout>
  28. </dk.touch.MyLayout>
  29. </dk.touch.MyLayout>
  30. </LinearLayout>
  31. 轻触center部分logcat输出结果

4.png

5.png

事件处理流程大致同上,区别是此状态下,所有组件都不会处理事件,事件并不会被centeronTouchEvent方法“消费”,则事件会层层逆向传递回到Activity,若Activity也不对此事件进行处理,此事件相当于消失了(无效果)。
对于后续的moveup事件,由于第一个down事件已经确定由Activity处理事件,故up事有由ActivitydispatchTouchEvent直接分发给自己的onTouchEvent方法处理。

  
  1. 源代码:
  2. package dk.touch;
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.view.MotionEvent;
  6. public class MainActivity extends Activity{
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.main);
  11. MyLayout out=(MyLayout) findViewById(R.id.out);
  12. out.setName("out");
  13. MyLayout middle=(MyLayout) findViewById(R.id.middle);
  14. middle.setName("middle");
  15. MyLayout center=(MyLayout) findViewById(R.id.center);
  16. center.setName("center");
  17. }
  18. @Override
  19. public boolean dispatchTouchEvent(MotionEvent ev) {
  20. int action=ev.getAction();
  21. String actionName="";
  22. switch(action)
  23. {
  24. case MotionEvent.ACTION_DOWN:
  25. actionName="ACTION_DOWN";
  26. break;
  27. case MotionEvent.ACTION_MOVE:
  28. actionName="ACTION_MOVE";
  29. break;
  30. case MotionEvent.ACTION_UP:
  31. actionName="ACTION_UP";
  32. break;
  33. }
  34. System.out.println("Activity"+"|"+actionName+":dispatchTouchEvent");
  35. return super.dispatchTouchEvent(ev);
  36. }
  37. @Override
  38. public boolean onTouchEvent(MotionEvent event) {
  39. int action=event.getAction();
  40. String actionName="";
  41. switch(action)
  42. {
  43. case MotionEvent.ACTION_DOWN:
  44. actionName="ACTION_DOWN";
  45. break;
  46. case MotionEvent.ACTION_MOVE:
  47. actionName="ACTION_MOVE";
  48. break;
  49. case MotionEvent.ACTION_UP:
  50. actionName="ACTION_UP";
  51. break;
  52. }
  53. System.out.println("Activity"+"|"+actionName+":onTouchEvent");
  54. return super.onTouchEvent(event);
  55. }
  56. }
  57. package dk.touch;
  58. import android.content.Context;
  59. import android.util.AttributeSet;
  60. import android.view.MotionEvent;
  61. import android.widget.LinearLayout;
  62. public class MyLayout extends LinearLayout {
  63. private String name="";
  64. public MyLayout(Context context, AttributeSet attrs) {
  65. super(context, attrs);
  66. }
  67. @Override
  68. public boolean onTouchEvent(MotionEvent event) {
  69. int action=event.getAction();
  70. String actionName="";
  71. switch(action)
  72. {
  73. case MotionEvent.ACTION_DOWN:
  74. actionName="ACTION_DOWN";
  75. break;
  76. case MotionEvent.ACTION_MOVE:
  77. actionName="ACTION_MOVE";
  78. break;
  79. case MotionEvent.ACTION_UP:
  80. actionName="ACTION_UP";
  81. break;
  82. }
  83. System.out.println(name+"|"+actionName+":onTouchEvent");
  84. return super.onTouchEvent(event);
  85. }
  86. @Override
  87. public boolean dispatchTouchEvent(MotionEvent ev) {
  88. int action=ev.getAction();
  89. String actionName="";
  90. switch(action)
  91. {
  92. case MotionEvent.ACTION_DOWN:
  93. actionName="ACTION_DOWN";
  94. break;
  95. case MotionEvent.ACTION_MOVE:
  96. actionName="ACTION_MOVE";
  97. break;
  98. case MotionEvent.ACTION_UP:
  99. actionName="ACTION_UP";
  100. break;
  101. }
  102. System.out.println(name+"|"+actionName+":dispatchTouchEvent");
  103. return super.dispatchTouchEvent(ev);
  104. }
  105. @Override
  106. public boolean onInterceptTouchEvent(MotionEvent ev) {
  107. int action=ev.getAction();
  108. String actionName="";
  109. switch(action)
  110. {
  111. case MotionEvent.ACTION_DOWN:
  112. actionName="ACTION_DOWN";
  113. break;
  114. case MotionEvent.ACTION_MOVE:
  115. actionName="ACTION_MOVE";
  116. break;
  117. case MotionEvent.ACTION_UP:
  118. actionName="ACTION_UP";
  119. break;
  120. }
  121. System.out.println(name+"|"+actionName+":onInterceptTouchEvent");
  122. return super.onInterceptTouchEvent(ev);
  123. }
  124. public String getName() {
  125. return name;
  126. }
  127. public void setName(String name) {
  128. this.name = name;
  129. }
  130. }

工程下载见:


Touch.7z.zip 

文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/8741201

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。