Android Touch事件总结 一

    xiaoxiao2021-12-14  18

    说明:本博客为原创,转载请注明出处 -ANDROID 笔记栈 由于作者水平有限,错误在所难免,请见谅,可以留言,本人会及时改正


    索引

    Activity View TouchEvent传递关系图Demo


    Android Touch事件主要有三个方法: dispatchTouchEvent(分发): Touch事件的入口方法 onInterceptTouchEvent(拦截):ViewGroup拦截事件,不传递给子View onTouchEvent(处理):是否消费事件

    Activity和View都可以处理TouchEvent事件,Activity是所有事件的入口

    TouchEvent 事件是从上而下,从外而内开始传递

    Activity(window、DecorView) -> ViewGroup -> View

    Activity View TouchEvent

    事件dispatchTouchEventonInterceptTouchEventonTouchEventActivity√×√ViewGroup√√√View√×√

    1.分发事件

    public boolean dispatchTouchEvent(MotionEvent ev) { return true; // true,MotionEvent已被消费 // 不调用**super.dispatchTouchEvent()**方法,其他两个方法是不会被调用的! // 该方法返回false,代表没有View对该事件进行消费,后续事件将不会被分发给你当前View。 // super.dispatchTouchEvent()返回结果是根据子View的dispatchTouchEvent方法或者当前View的onTouchEvent方法的返回结果而决定的。 // 在ViewGroup中,根据特定的排列顺序遍历子Child,调用子View的dispatchTouchEvent的方法来实现事件的分发。 // (Actvity 永远接收dispatchTouchEvent事件) }

    -如果TouchEvent事件在传递过程中,没有View/ViewGroup对“DOWN”事件进行消费,后续TouchEvent事件(MOVE,UP,CANCEL等)只会被分发到Activity中。

    2.拦截事件

    public boolean onInterceptTouchEvent(MotionEvent ev) { return true; // true,MotionEvent被当前ViewGroup拦截 //不会传递给子View的dispatchTouchEvent(),ViewGroup的onTouchEvent()会被调用。 //这个方法,SDK文档中有如下说明:(翻译的水平有限,请见谅) //1.在这个方法中可以接收“DOWN”事件 //2.... //3.这个方法返回false,后续事件将会先传递到该方法,随后传到后onTouch方法中 //4.这个方法返回true,你将不会接收到如下事件:目标View将会接收到一个CANCEL事件,所有的后续事件将会被传递到onTouchEvnet方法中,该方法将不再接收事件 }

    onInterceptTouchEvent不是很好理解,可以参考这篇博文:Android 触摸事件机制(四) ViewGroup中触摸事件详解

    3.处理事件

    public boolean onTouchEvent(MotionEvent ev) { return true; // true,MotionEvent被消费 }

    传递关系图

    ViewGroup中的onInterceptTouchEvent方法,在Action为“DOWN”的时候或者ViewGroup子View有消费TouchEvnet事件的时候(可能有多个子View对TouchEvnet事件进行相应,这些View组成了TouchTarget链表)会被调用


    Demo

    GitHub地址: GitHub 环境: Windows7+JAVA8 IDE: AndroidStdio2.2.2 compileSdkVersion:24 测试设备:Nexus5(6.0.1)

    Demo中存在多个示例,请在Manifest中更改启动项。

    自定义DLFrameLayout继承与FrameLayout,自定义DLView继承与View

    分别重载Touch事件的方法,输出日志,代码如下:

    @Override public boolean dispatchTouchEvent(MotionEvent ev) { DLDebug.info(TAG, "dispatchTouchEvent: " + TouchEventHelper.parseAction((ev.getActionMasked())));//输出日志 boolean dispatchTouchEvent = mDispatchTouchEvent; if (mSuperDispatchTouchEvent)//是否调用super方法 { dispatchTouchEvent = super.dispatchTouchEvent(ev) || mDispatchTouchEvent; } DLDebug.info(TAG, "dispatchTouchEvent: " + dispatchTouchEvent);//输出日志,true/false return dispatchTouchEvent; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { DLDebug.info(TAG, "onInterceptTouchEvent: " + TouchEventHelper.parseAction((ev.getActionMasked()))); boolean onInterceptTouchEvent = mInterceptTouchEvent; if (mSuperInterceptTouchEvent) { onInterceptTouchEvent = super.onInterceptTouchEvent(ev) || mInterceptTouchEvent; } DLDebug.info(TAG, "onInterceptTouchEvent: " + onInterceptTouchEvent); return onInterceptTouchEvent; } @Override public boolean onTouchEvent(MotionEvent ev) { DLDebug.info(TAG, "onTouchEvent: " + TouchEventHelper.parseAction((ev.getActionMasked()))); boolean onTouchEvent = mTouchEvent; if (mSuperTouchEvent) { onTouchEvent = super.onTouchEvent(ev) || mTouchEvent; } DLDebug.info(TAG, "onTouchEvent: " + onTouchEvent); return onTouchEvent; } 验证结果 如果自定义View所有方法都返回false,那么后续事件不会被传递到View或者ViewGroup中,只会被传递到Activity中输出日志如下: 12-05 15:10:35.440 V/DL_MainActivity: dispatchTouchEvent: DOWN 12-05 15:10:35.440 I/DL_DLFrameLayout: dispatchTouchEvent: DOWN 12-05 15:10:35.440 I/DL_DLFrameLayout: onInterceptTouchEvent: DOWN 12-05 15:10:35.440 I/DL_DLFrameLayout: onInterceptTouchEvent: false 12-05 15:10:35.440 D/DL_DLView: dispatchTouchEvent: DOWN 12-05 15:10:35.441 D/DL_DLView: onTouchEvent: DOWN 12-05 15:10:35.441 D/DL_DLView: onTouchEvent: false 12-05 15:10:35.441 D/DL_DLView: dispatchTouchEvent: false 12-05 15:10:35.441 I/DL_DLFrameLayout: onTouchEvent: DOWN 12-05 15:10:35.441 I/DL_DLFrameLayout: onTouchEvent: false 12-05 15:10:35.441 I/DL_DLFrameLayout: dispatchTouchEvent: false 12-05 15:10:35.441 V/DL_MainActivity: onTouchEvent: DOWN 12-05 15:10:35.441 V/DL_MainActivity: onTouchEvent: false 12-05 15:10:35.441 V/DL_MainActivity: dispatchTouchEvent: false 12-05 15:10:35.634 V/DL_MainActivity: dispatchTouchEvent: MOVE 12-05 15:10:35.634 V/DL_MainActivity: onTouchEvent: MOVE 12-05 15:10:35.634 V/DL_MainActivity: onTouchEvent: false 12-05 15:10:35.634 V/DL_MainActivity: dispatchTouchEvent: false .... 12-05 15:10:36.021 V/DL_MainActivity: dispatchTouchEvent: UP 12-05 15:10:36.021 V/DL_MainActivity: onTouchEvent: UP 12-05 15:10:36.021 V/DL_MainActivity: onTouchEvent: false 12-05 15:10:36.021 V/DL_MainActivity: dispatchTouchEvent: false // 根据日志可以看出,后续的MOVE/UP事件没有传递到自定义View中。 验证结果如果ViewGroup onInterceptTouchEvent()中返回true,并且onTouchEvent()中也返回true,那么事件不会被传递到子View中,并且能接收后续事件。

    输入日志如下:

    12-05 15:38:03.241 V/DL_MainActivity: dispatchTouchEvent: DOWN 12-05 15:38:03.241 I/DL_DLFrameLayout: dispatchTouchEvent: DOWN 12-05 15:38:03.241 I/DL_DLFrameLayout: onInterceptTouchEvent: DOWN 12-05 15:38:03.241 I/DL_DLFrameLayout: onInterceptTouchEvent: true 12-05 15:38:03.241 I/DL_DLFrameLayout: onTouchEvent: DOWN 12-05 15:38:03.241 I/DL_DLFrameLayout: onTouchEvent: true 12-05 15:38:03.241 I/DL_DLFrameLayout: dispatchTouchEvent: true 12-05 15:38:03.242 V/DL_MainActivity: dispatchTouchEvent: true 12-05 15:38:03.268 V/DL_MainActivity: dispatchTouchEvent: MOVE 12-05 15:38:03.268 I/DL_DLFrameLayout: dispatchTouchEvent: MOVE 12-05 15:38:03.268 I/DL_DLFrameLayout: onTouchEvent: MOVE 12-05 15:38:03.269 I/DL_DLFrameLayout: onTouchEvent: true 12-05 15:38:03.269 I/DL_DLFrameLayout: dispatchTouchEvent: true 12-05 15:38:03.269 V/DL_MainActivity: dispatchTouchEvent: true 12-05 15:38:03.285 V/DL_MainActivity: dispatchTouchEvent: MOVE 12-05 15:38:03.285 I/DL_DLFrameLayout: dispatchTouchEvent: MOVE 12-05 15:38:03.285 I/DL_DLFrameLayout: onTouchEvent: MOVE 12-05 15:38:03.285 I/DL_DLFrameLayout: onTouchEvent: true 12-05 15:38:03.285 I/DL_DLFrameLayout: dispatchTouchEvent: true 12-05 15:38:03.285 V/DL_MainActivity: dispatchTouchEvent: true 12-05 15:38:03.302 V/DL_MainActivity: dispatchTouchEvent: MOVE 12-05 15:38:03.302 I/DL_DLFrameLayout: dispatchTouchEvent: MOVE 12-05 15:38:03.302 I/DL_DLFrameLayout: onTouchEvent: MOVE 12-05 15:38:03.302 I/DL_DLFrameLayout: onTouchEvent: true 12-05 15:38:03.302 I/DL_DLFrameLayout: dispatchTouchEvent: true 12-05 15:38:03.302 V/DL_MainActivity: dispatchTouchEvent: true 12-05 15:38:03.318 V/DL_MainActivity: dispatchTouchEvent: MOVE 12-05 15:38:03.318 I/DL_DLFrameLayout: dispatchTouchEvent: MOVE 12-05 15:38:03.318 I/DL_DLFrameLayout: onTouchEvent: MOVE 12-05 15:38:03.318 I/DL_DLFrameLayout: onTouchEvent: true 12-05 15:38:03.318 I/DL_DLFrameLayout: dispatchTouchEvent: true 12-05 15:38:03.318 V/DL_MainActivity: dispatchTouchEvent: true 12-05 15:38:03.323 V/DL_MainActivity: dispatchTouchEvent: UP 12-05 15:38:03.323 I/DL_DLFrameLayout: dispatchTouchEvent: UP 12-05 15:38:03.323 I/DL_DLFrameLayout: onTouchEvent: UP 12-05 15:38:03.323 I/DL_DLFrameLayout: onTouchEvent: true 12-05 15:38:03.323 I/DL_DLFrameLayout: dispatchTouchEvent: true 12-05 15:38:03.323 V/DL_MainActivity: dispatchTouchEvent: true //事件确实没有传递到子View中,ViewGroup接收了MOVE/UP事件

    大家可以下载源码,察看其他情况下的输出结果


    转载请注明原文地址: https://ju.6miu.com/read-964541.html

    最新回复(0)