Android中view的Touch事件传递顺序
先看一下ViewGroup的dispatchTouchEvent的关键源码:
public boolean dispatchTouchEvent(MotionEvent ev) {... if (action == MotionEvent.ACTION_DOWN) {... if (disallowIntercept || !onInterceptTouchEvent(ev)) { final View[] children = mChildren; final int count = mChildrenCount; for (int i = count - 1; i >= 0; i--) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { ... if (child.dispatchTouchEvent(ev)) { // Event handled, we have a target now. mMotionTarget = child; return true; } } } } }... final View target = mMotionTarget; if (target == null) {... return super.dispatchTouchEvent(ev); } if (!disallowIntercept && onInterceptTouchEvent(ev)) { ... if (!target.dispatchTouchEvent(ev)) { // target didn't handle ACTION_CANCEL. not much we can do // but they should have. } // clear the target mMotionTarget = null; // Don't dispatch this event to our own view, because we already // saw it when intercepting; we just want to give the following // event to the normal onTouchEvent(). return true; }... return target.dispatchTouchEvent(ev); }根据以上代码可知,如果onInterceptTouchEvent方法返回true,会直接调用当前ViewGroup的onTouch方法,否则则会依次调用其内包含的子控件的dispatchTouchEvent方法。我写了一个测试用例,ViewGroup的onInterceptTouchEvent方法与所有View的onTouch方法都打了Log:
<?xml version="1.0" encoding="utf-8"?><org.gavin.test.view.MyScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" ><org.gavin.test.view.MyLinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <org.gavin.test.view.MyImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher"></org.gavin.test.view.MyImageView></org.gavin.test.view.MyLinearLayout></org.gavin.test.view.MyScrollView>Log信息:
I/MyScrollView(26001): onInterceptTouchEvent:MotionEvent{404ea7c8 action=0 x=34.215885 y=51.963867 pressure=0.14117648 size=0.1}
I/MyLinearLayout(26001): onInterceptTouchEvent:MotionEvent{404ea7c8 action=0 x=34.215885 y=51.963867 pressure=0.14117648 size=0.1}
I/MyImageView(26001): onTouchEvent:MotionEvent{404ea7c8 action=0 x=34.215885 y=51.963867 pressure=0.14117648 size=0.1}
I/MyLinearLayout(26001): onTouchEvent:MotionEvent{404ea7c8 action=0 x=34.215885 y=51.963867 pressure=0.14117648 size=0.1}
I/MyScrollView(26001): onTouchEvent:MotionEvent{404ea7c8 action=0 x=34.215885 y=51.963867 pressure=0.14117648 size=0.1}
如果MyLinearLayout的onInterceptTouchEvent方法返回true:
11-04 14:05:08.389: I/MyScrollView(26297): onInterceptTouchEvent:MotionEvent{404e9ed0 action=0 x=24.439919 y=41.980873 pressure=0.13333334 size=0.15}
11-04 14:05:08.389: I/MyLinearLayout(26297): onInterceptTouchEvent:MotionEvent{404e9ed0 action=0 x=24.439919 y=41.980873 pressure=0.13333334 size=0.15}
11-04 14:05:08.397: I/MyLinearLayout(26297): onTouchEvent:MotionEvent{404e9ed0 action=0 x=24.439919 y=41.980873 pressure=0.13333334 size=0.15}
11-04 14:05:08.397: I/MyScrollView(26297): onTouchEvent:MotionEvent{404e9ed0 action=0 x=24.439919 y=41.980873 pressure=0.13333334 size=0.15}
OK,再看这段代码:
if (child.dispatchTouchEvent(ev)) { // Event handled, we have a target now. mMotionTarget = child; return true; }从这段代码可以看出,如果某个子控件的dispatchTouchEvent方法返回true,则中断以后的消息传递。并在下一个非ACTION_DOWN事件直接调用此子控件的dispatchTouchEvent方法。一个View的dispatchTouchEvent返回true,主要可能是onTouch方法返回true。如果我们把MyImageView的onTouchEvent返回值改为true:
I/MyScrollView(26393): onInterceptTouchEvent:MotionEvent{404eb2b0 action=0 x=32.749493 y=51.05632 pressure=0.11764707 size=0.1}
/MyLinearLayout(26393): onInterceptTouchEvent:MotionEvent{404eb2b0 action=0 x=32.749493 y=51.05632 pressure=0.11764707 size=0.1}
I/MyImageView(26393): onTouchEvent:MotionEvent{404eb2b0 action=0 x=32.749493 y=51.05632 pressure=0.11764707 size=0.1}
更多相关文章
- Android自定义dialog简单实现方法
- Android中发短信的代码
- android使用sharedPreferences()方法读写文件操作
- android studio 代码混淆
- Android getWindow().setFlags方法 设置窗体全屏点亮背景模糊 &&
- Android 混淆代码的时候出现问题
- Android:Activity中onCreate方法的参数及用途
- 有关android安全性的问题--代码混淆
- Android NDK so crash,定位目标代码使用