您的位置:首页 > 移动开发 > Android开发

Android触摸事件传递机制学习笔记

2015-08-07 15:50 756 查看
1、Android 触摸事件传递机制

/article/9242824.html

2、Android-onInterceptTouchEvent()和onTouchEvent()总结

/article/8007182.html

3、Android onTouchEvent, onClick及onLongClick的调用机制

/article/8105930.html

4、Android: 详解触摸事件如何传递

http://www.cnblogs.com/superlcr/p/3946034.html?utm_source=tuicool

一、涉及的类和方法

Activity,View,ViewGroup(View的子类)

1)public boolean dispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent,在Activity和View里分别定义

这个方法尝试将触摸事件交给自己的子视图 (如果有的话) 处理: 调用子视图的 dispatchTouchEvent()

或者自己处理: 调用自己的 onTouchEvent() 或 OnTouchListener.onTouch()(优先调用)

无论是自己的子视图,还是自己,只要完成了事件处理,都返回 true

2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent

ViewGroup单独定义的方法,如果事件需要在该 ViewGroup 截断 (自己处理该事件, 不再传递给其子视图), 则返回 true

3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent 在Activity和View里分别定义

这个方法尝试自己处理触摸事件. 如果完成处理 (不需要再交给其他 View 处理), 则返回 true

二,传递流程

从Activity的dispatchTouchEvent开始,这是触摸事件的入口,没有重写的情况下会无条件的传递给根视图ViewGroup的dispatchTouchEvent,经过如下图的流程,返回true表示ViewGroup消费了事件,返回false则返回Activity自己的 onTouchEvent() 方法。



如果ViewGroup 还有子视图,且仍然没有截断的话,会继续调用子视图的子视图,如此递归进行。触摸事件派遣的顺序是自上而下的。直到到达某个叶子 View (不再有子视图可以派遣),或者某个 ViewGroup 虽然还有子视图可以派遣,但其截断 onInterceptTouchEvent() 方法返回 true。这时,触摸事件真正开始尝试进行处理。

处理方法:如果注册了触摸事件监听器 OnTouchLisener,则优先调用 OnTouchLisener.onTouch() 方法,如果没有注册监听器,或OnTouchLisener.onTouch() 方法返回 false,再尝试调用 ViewGroup 自身的 onTouchEvent() 方法

如果该 View 完成了触摸事件的处理 (返回 true),那么对于其父视图而言,dispatchTouchEvent() 方法派遣给子视图的事件圆满完成,可以向自己的父视图宣称完成事件了 (返回 true)。反之,如果该 View 自己没有完成触摸事件,对于其父视图 ViewGroup 而言,派遣子视图并没有完成事件处理,只好自己处理。如果再次没有完成,父视图会向自己的父视图返回 false,如果各层 ViewGroup 均不能完成事件处理,最终会调用 Activity 的 onTouchEvent() 方法,做最后的尝试。整个实际处理过程顺序正好相反,是自下而上的。

三、onClick、onLongClick和onTouchEvent

在 onTouchEvent() 中,会判断触摸是否构成一次点击事件,从而交给其他一些监听器,如 onClickListener (监听点击事件),onLongClickListener (监听长按事件) 来处理,同时返回 true。

onTouchEvent()方法的判断:

case MotionEvent.ACTION_DOWN:
mPrivateFlags |= PRESSED;
refreshDrawableState();
if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
postCheckForLongClick(); //发起CheckForLongPress线程的执行,条件都满足后会设置OnLongClickListener
}
break;

case MotionEvent.ACTION_UP:
if ((mPrivateFlags & PRESSED) != 0) {
boolean focusTaken = false;
if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
focusTaken = requestFocus();
}
if (!mHasPerformedLongPress) {
if (mPendingCheckForLongPress != null) {
removeCallbacks(mPendingCheckForLongPress);
}

if (!focusTaken) {
performClick();//设置OnClickListener
}
}
…
break;


长按事件顺序:onTouch ACTION_DOWN——onLongClick——onTouch ACTION_UP

点击事件顺序:onTouch ACTION_DOWN——onTouch ACTION_UP——onClick

onLongClick的发生是在ACTION_UP之前,而onClick的发生是在ACTION_UP后,如果在onLongClick()方法的最后return true,则不会再触发onClick;如果return false的话会在ACTION_UP后仍然触发onClick。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: