dispatchTouchEvent:
- 方法返回值为 true 表示事件被当前视图消费掉;
- 返回为super.dispatchTouchEvent 表示继续分发该事件,
- 返回为 false 表示交给父类的onTouchEvent 处理。
onInterceptTouchEvent:
- 方法返回值为 true 表示拦截这个事件并交由自身的onTouchEvent 方法进行消费;
- 返回 false 表示不拦截,需要继续传递给子视图。
- 如果 return super.onInterceptTouchEvent(ev), 事件拦截分两种情况:
- 如果该View存在子View且点击到了该子View, 则不拦截, 继续分发 给子 View 处理, 此时相当于 return false。
- 如果该 View 没有子 View 或者有子 View 但是没有点击中子 View(此时ViewGroup 相当于普通 View), 则交由该 View 的 onTouchEvent 响应,此时相当于 return true。
注意:一般的 LinearLayout、 RelativeLayout、FrameLayout 等 ViewGroup 默认不拦截, 而 ScrollView、ListView 等 ViewGroup 则可能拦截,得看具体情况。
onTouchEvent:
- 方法返回值为 true 表示当前视图可以处理对应的事件;
- 返回值为 false 表示当前视图不处理这个事件,它会被传递给父视图的 onTouchEvent方法进行处理。
- 如果 return super.onTouchEvent(ev),事件处理分为两种情况:
- 如果该 View 是 clickable 或者 longclickable 的,则会返回 true, 表示消费了该事件, 与返回 true 一样;
- 如果该 View 不是 clickable 或者 longclickable 的,则会返回 false, 表示不消费该事件,将会向上传递,与返回 false 一样。
一些重要的结论:
- 注意:在 Android 系统中,拥有事件传递处理能力的类有以下三种:
- Activity:拥有分发和消费两个方法。
- ViewGroup:拥有分发、拦截和消费三个方法。
- View:拥有分发、消费两个方法。
- 事件传递优先级:
- onTouchListener.onTouch > onTouchEvent > onClickListener.onClick。
- 正常情况下,一个时间序列只能被一个 View拦截且消耗。因为一旦一个元素拦截了此事件,那么同一个事件序列内的所有事件都会直接交给它处理(即不会再调用这个 View的拦截方法去询问它是否要拦截了,而是把剩余的ACTION_MOVE、ACTION_DOWN等事件直接交给它来处理)。特例:通过将重写 View 的onTouchEvent 返回false 可强行将事件转交给其他View 处理。
- 如果 View 不消耗除 ACTION_DOWN以外的其他事件,那么这个点击事件会消失,此时父元素的 onTouchEvent 并不会被调用,并且当前 View可以持续收到后续的事件,最终这些消失的点击事件会传递给 Activity 处理。
- ViewGroup默认不拦截任何事件(返回false)。
- View 的 onTouchEvent 默认都会消耗事件(返回true),除非它是不可点击 的(clickable和 longClickable 同时为 false)。View 的 longClickable属性默认 都为 false,clickable属性要分情况,比如 Button 的 clickable 属性默认为 true, 而TextView 的 clickable 默认为false。
- View 的 enable 属性不影响 onTouchEvent 的默认返回值。
- 通过requestDisallowInterceptTouchEvent 方法可以在子元素中干预父元素的事件分发过程,但是ACTION_DOWN 事件除外。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END