Android系统中TouchEvent的传递流程以及相关函数返回值True和False对流程的影响
来源:互联网 发布:mac怎么连接打印机 编辑:程序博客网 时间:2024/05/22 14:32
3个关键函数
public boolean onInterceptTouchEvent (MotionEvent ev)
Added in API level 1
Implement this method to intercept all touch screen motion events. This allows you to watch events as they are dispatched to your children, and take ownership of the current gesture at any point.
Using this function takes some care, as it has a fairly complicated interaction with
View.onTouchEvent(MotionEvent)
, and using it requires implementing that method as well as this one in the correct way. Events will be received in the following order:- You will receive the down event here.
- The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal
- For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().
- If you return true from here, you will not receive any following events: the target view will receive the same event but with the action
ACTION_CANCEL
, and all further events will be delivered to your onTouchEvent() method and no longer appear here.
Parameters
Returns
- Return true to steal motion events from the children and have them dispatched to this ViewGroup through onTouchEvent(). The current target will receive an ACTION_CANCEL event, and no further messages will be delivered here
public boolean dispatchTouchEvent (MotionEvent ev)
Added in API level 1
Pass the touch screen motion event down to the target view, or this view if it is the target.
Parameters
Returns
- True if the event was handled by the view, false otherwise.
public boolean onTouchEvent (MotionEvent event)
Added in API level 1
Implement this method to handle touch screen motion events.
If this method is used to detect click actions, it is recommended that the actions be performed by implementing and calling performClick()
. This will ensure consistent system behavior, including:
- obeying click sound preferences
- dispatching OnClickListener calls
- handling
ACTION_CLICK
when accessibility features are enabled
Parameters
Returns
- True if the event was handled, false otherwise.
2个关键类:View ViewGroup
一、概述
- View类有dispatchTouchEvent、onTouchEvent两个函数。ViewGroup集成自View,有dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三个函数。
- TouchEvent是由父视图向子视图传递的,在视图树上表现是根向叶子传递。
- TouchEvent会不断被传递,但只会被处理一次。
二、View对TouchEvent的处理流程
- 父视图通过调用当前视图的dispatchTouchEvent函数将TouchEvent传递给当前视图
- 当前视图判断自身是否注册了onTouchListener、是否Enabled、注册的onTouchListener是否返回True,如果这些条件全部满足,意味着TouchEvent被onTouchListener处理了。那么也就不需要调用当前视图的onTouchEvent函数了,直接返回True告诉父视图,”你传递给我的TouchEvent我已经处理了”。
- 否则调用当前视图的onTouchEvent函数
View中的dispatchTouchEvent函数
- public boolean dispatchTouchEvent(MotionEvent event) {
- if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
- mOnTouchListener.onTouch(this, event)) {
- return true;
- }
- return onTouchEvent(event);
- }
三、ViewGroup对TouchEvent的处理流程
- 同View一样,父视图会调用ViewGroup的dispatchTouchEvent函数,这是ViewGroup对TouchEvent的处理的起点
- ViewGroup的dispatchTouchEvent函数相对于View中的dispatchTouchEvent函数来说复杂一点。因为它要额外做两件事,一是判断要不要截获TouchEvent,二是维护一个TouchEvent的目标视图。
- 判断要不要截获TouchEvent
解释一下doc里面的几点
- The down event will be handled either by a child of this viewgroup, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal. 如果你在这里返回true,在onTouchEvent函数里也返回true,可以接收到手势的后续事件。这里的收到,是指onTouchEvent收到。这种情况下,onInterceptTouchEvent获取不到了。因为你在onTouchEvent里面对down event返回了true,表示你要处理这个手势,你也就成为了这个手势目标视图,那么这个手势的后续事件,view group将直接发送给你,而不再考虑分发给子视图,也就不存在要不要截获的问题,自然也就不会调用onInterceptTouchEvent,所以后续的手势onInterceptTouchEvent获取不到。
- For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().如果你从这个函数返回false,那么后续的事件都会在这个函数里出现,然后分发给目标视图的onTouchEvent函数处理。
- **
- * Implement this method to intercept all touch screen motion events. This
- * allows you to watch events as they are dispatched to your children, and
- * take ownership of the current gesture at any point.
- *
- * <p>Using this function takes some care, as it has a fairly complicated
- * interaction with {@link View#onTouchEvent(MotionEvent)
- * View.onTouchEvent(MotionEvent)}, and using it requires implementing
- * that method as well as this one in the correct way. Events will be
- * received in the following order:
- *
- * <ol>
- * <li> You will receive the down event here.
- * <li> The down event will be handled either by a child of this view
- * group, or given to your own onTouchEvent() method to handle; this means
- * you should implement onTouchEvent() to return true, so you will
- * continue to see the rest of the gesture (instead of looking for
- * a parent view to handle it). Also, by returning true from
- * onTouchEvent(), you will not receive any following
- * events in onInterceptTouchEvent() and all touch processing must
- * happen in onTouchEvent() like normal.
- * <li> For as long as you return false from this function, each following
- * event (up to and including the final up) will be delivered first here
- * and then to the target's onTouchEvent().
- * <li> If you return true from here, you will not receive any
- * following events: the target view will receive the same event but
- * with the action {@link MotionEvent#ACTION_CANCEL}, and all further
- * events will be delivered to your onTouchEvent() method and no longer
- * appear here.
- * </ol>
- *
- * @param ev The motion event being dispatched down the hierarchy.
- * @return Return true to steal motion events from the children and have
- * them dispatched to this ViewGroup through onTouchEvent().
- * The current target will receive an ACTION_CANCEL event, and no further
- * messages will be delivered here.
- */
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- return false;
- }
四、ViewGroup onInterceptTouchEvent接收到TouchEvent情况分析
查看源码发现,Android4.0对ViewGroup的dispatchTouchEvent函数做了修改。Android4.0以上版本和以下版本onInterceptTouchEvent接收到TouchEvent情况是不同的。这里主要分析Android4.0以上版本onInterceptTouchEvent接收到TouchEvent情况。
分析的主要内容有
- onInterceptTouchEvent接收TouchEvent受哪些因素影响
- onInterceptTouchEvent将接收到哪些类型的TouchEvent
先看源码
再说结论
- 一个手势是一个周期,下一个手势与上一个手势相同对待
- onInterceptTouchEvent总是能接受到down event
- 如果onInterceptTouchEvent在接收到down event时返回false的话,而子视图在dispatchTouchEvent中返回true的话,那么这个手势的后续事件都会被接收到
- 如果onInterceptTouchEvent在接收到down event时返回false的话,而子视图在dispatchTouchEvent中返回false的话,那么这个手势的后续事件不会被接收到
- 如果onInterceptTouchEvent在接收到down event时返回true的话,那么这个手势的后续事件不会被接收到
进行验证
验证3
package com.example.ligang.demo_autopullrefreshlistview;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.MotionEvent;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.TextView;public class TestInterceptActivity extends Activity { private final static String TAG = TestInterceptActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyViewGroup viewGroup = new MyViewGroup(this); MyView view = new MyView(this); view.setText("hello"); viewGroup.addView(view); setContentView(viewGroup); } class MyViewGroup extends LinearLayout { public MyViewGroup(Context context) { super(context); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: Log.e(TAG, "ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.e(TAG, "ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.e(TAG, "ACTION_UP"); break; case MotionEvent.ACTION_CANCEL: Log.e(TAG, "ACTION_CANCEL"); break; default: break; } return false; } @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); } } class MyView extends TextView { public MyView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { return true; } }}
验证4
package com.example.ligang.demo_autopullrefreshlistview;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.MotionEvent;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.TextView;public class TestInterceptActivity extends Activity { private final static String TAG = TestInterceptActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyViewGroup viewGroup = new MyViewGroup(this); MyView view = new MyView(this); view.setText("hello"); viewGroup.addView(view); setContentView(viewGroup); } class MyViewGroup extends LinearLayout { public MyViewGroup(Context context) { super(context); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: Log.e(TAG, "ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.e(TAG, "ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.e(TAG, "ACTION_UP"); break; case MotionEvent.ACTION_CANCEL: Log.e(TAG, "ACTION_CANCEL"); break; default: break; } return false; } @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); } } class MyView extends TextView { public MyView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { return false; } }}
验证5
package com.example.ligang.demo_autopullrefreshlistview;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.MotionEvent;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.TextView;public class TestInterceptActivity extends Activity { private final static String TAG = TestInterceptActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyViewGroup viewGroup = new MyViewGroup(this); MyView view = new MyView(this); view.setText("hello"); viewGroup.addView(view); setContentView(viewGroup); } class MyViewGroup extends LinearLayout { public MyViewGroup(Context context) { super(context); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: Log.e(TAG, "ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.e(TAG, "ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.e(TAG, "ACTION_UP"); break; case MotionEvent.ACTION_CANCEL: Log.e(TAG, "ACTION_CANCEL"); break; default: break; } return true; } @Override public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); } } class MyView extends TextView { public MyView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { return false; } }}
0 0
- Android系统中TouchEvent的传递流程以及相关函数返回值True和False对流程的影响
- js中 [] ? true : false 的返回值为什么是true?
- 语言编程中返回false和true的易错点
- Android TouchEvent的传递
- 浅析Android的setOnTouchListener的返回值是false和true的区别
- setOnTouchEvent 设置返回值为true 和 false的区别
- setOnTouchEvent 设置返回值为true 和 false的区别
- setOnTouchEvent 设置返回值为true 和 false的区别
- [android] setOnTouchEvent 设置返回值为true 和 false的区别
- js中逻辑运算符|| 的返回值并不只有true和false
- [置顶] Android输入输出系统之TouchEvent流程
- HBase Flush操作流程以及对读写服务的影响
- HBase Flush操作流程以及对读写服务的影响
- Android TouchEvent 分发流程
- Android TouchEvent 分发流程
- Android TouchEvent 分发流程
- Android TouchEvent 分发流程
- Android TouchEvent 分发流程
- 九度OJ—题目1050:完数
- 开源中国广州源创会分享
- 自定义组合控件
- 常用防反接电路
- Spring框架学习(二) 之 jar包
- Android系统中TouchEvent的传递流程以及相关函数返回值True和False对流程的影响
- 输入两个数,第一个数决定一个nXn的矩阵
- C语言结构体声明中冒号的使用(占位符) & C结构体的乱序初始化
- 滚动页面,然后再执行CSS3 动画
- keil4下同时用arm和51
- 【有图】android通过jdbc连接mysql(附文件)
- 当fscanf碰上nan
- String.valueOf(que[i]).getBytes()含义
- Tomcat的虚拟目录的创建步骤