Android 触摸事件处理机制
Android 触摸事件的处理主要涉及到几个方法:onInterceptTouchEvent(), dipatchTouchEvent(), onTouchEvent(), onTouch()。
onInterceptTouchEvent() 用于拦截事件并改变事件传递方向。解释一下事件传递。比如一个Activity中展示给用户可能是ViewGroup和View的多层嵌套,默认情况下触摸事件产生之后从最外层一次传递到最里面一层,然后在从最里面一层开始响应。从最里面一层开始依次调用各层次的dispatchTouchEvent()进行分发,dispatchTouchEvent()中在调用onTouch / onTouchEvent进行响应触摸事件。
onInterceptTouchEvent() 方法可以将触摸事件的传递截断,让触摸事件在某一层就不往下面传递,就开始调用这一层的dispatchTouchEvent(),开始向上层返回。如果需要在某一层拦截,需要复写该层的onInterceptTouchEvent()方法,并让该方法返回 true。通过一张图来解释一下。
假设一个Activity展示的界面有A->B->C->D四层,当事件发生之后,首先经过A的onInterceptTouchEvent(), 如果A的onInterceptTouchEvent()返回false,则会传递到B的onInterceptTouchEvent(),如果返回false则一次向下(内层)传递。如果某一层的onInterceptTouchEvent()返回true,然后就会调用该层的disatchTouchEvent()分发事件,事件不再向下传递。如果各层都没有拦截事件则从最内层开始调用dispatchTouchEvent(),如果某一各层的dispatchTouchEvent()返回true,则表明该层消费了该事件,则上面层的dispatchTouEvent()不会被调用。举一个例子:
上图中B层的onInterceptTouchEvent()返回true,则事件被拦截,开始调用B层的dispatchTouchEvent()向上返回一次响应触摸事件。
知道这个机制有什么卵用吗?
一个简单例子,我们在scrollView中放置了图片,图片允许缩放拖动,但是你对图片进行拖动的时候会发现scrollView也跟着动,这样体验就会很不好,怎么办呢?
结合上面的分析,我们可以知道,如果让触摸事件传递到内层的图片,然后在在图片的disPatchTouchEvent()中把这个触摸事件消费了就不就可以了吗?
具体做法在图片的onTouch() 方法中,ACTION_DOWN中设置scrollView不拦截事件,通过scrollView.requestDisallowInterceptTouchEvent(true)来完成,完成想要的处理之后在图片的onTouch()方法最后返回true就可以实现了。
问题又来了 onTouch(View v, MotionEvent event) 和 onTouchEvent(MotionEvent event) 有什么区别呢? 看起来那么像,不会是完成相同的功能吧?这样做不是多此一举吗,为什么不用一个就好了。
为了搞清楚这个问题,首先需要来看View中disPatchTouchEvent()方法:
public boolean dispatchTouchEvent(MotionEvent event) {
// If the event should be handled by accessibility focus first.
if (event.isTargetAccessibilityFocus()) {
// We don't have focus or no virtual descendant has it, do not handle the event.
if (!isAccessibilityFocusedViewOrHost()) {
return false;
}
// We have focus and got the event, then use normal event dispatch.
event.setTargetAccessibilityFocus(false);
} boolean result = false; if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
} final int actionMasked = event.getActionMasked();
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Defensive cleanup for new gesture
stopNestedScroll();
} if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
} if (!result && onTouchEvent(event)) {
result = true;
}
} if (!result && mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
} // Clean up after nested scrolls if this is the end of a gesture;
// also cancel it if we tried an ACTION_DOWN but we didn't want the rest
// of the gesture.
if (actionMasked == MotionEvent.ACTION_UP ||
actionMasked == MotionEvent.ACTION_CANCEL ||
(actionMasked == MotionEvent.ACTION_DOWN && !result)) {
stopNestedScroll();
} return result;
}
从上面可以看出onTouch() 先于 onTouchEvent()执行。通过查看View的源码还发现,或者简单推理一下我们设置setOnTouchListener()设置的是谁就知道,我们什么时候需要调用onTouch()方法让其发挥作用而不是让onTouchEvent()来响应了。View源码中可以看出onTouch是一个Interface的方式实现,将处理逻辑的实现交给开发者自定义,因此可以得出Android系统自带的控件我们使用onTouch处理事件,如果我们需要扩展View,则需要复写onTouchEvent()来实现事件的处理。其实onTouch(View v, MotionEvent event) 和 onTouchEvent(MotionEvent event)可以从这两个方法接受的参数就可以看出不同来,onTouch包含一个View类型的参数,因此是可以设置给某个View的,onTouchEvent()则是给某个View自己用的。
既然提到了View的事件响应,那onClick事件又是怎么响应的呢? 通过产看源码可以发现onClick是在onTouchEvent中执行的,而且是在onTouchEvent的ACTION_UP事件中执行的。因此如果View 的onTouch()返回true则会导致onClick得不到执行,因为onTouchEvent()得不到执行。
此外Activity中也有onTouchEvent()成员方法,如果Activity中的View都不处理Event则Activity的onTouchEvent()会调用。
Android 触摸事件处理机制的更多相关文章
- Android的事件处理机制详解(二)-----基于监听的事件处理机制
基于监听的事件处理机制 前言: 我们开发的app更多的时候是需要与用户的交互----即对用户的操作进行响应 这就涉及到了android的事件处理机制; android给我们提供了两套功能强大的处理机制 ...
- Android的事件处理机制(一)------基于回调机制的事件处理
Android平台的事件处理机制有两种,一种是基于回调机制的,一种是基于监听接口的,现介绍第一种:基于回调机制的事件处理.Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通 ...
- Android的事件处理机制之基于回调的事件处理
回调机制 如果说事件监听机制是一种委托式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源与事件监听器是统一的,换种方法说事件监听器完全消失了,当用户在GUI组件上激发某个事件 ...
- Android的事件处理机制之基于监听的事件处理
无论是桌面应用还是手机应用程序,面对用户的使用,经常需要处理的便是用户的各种动作,也就是需要为用户动作提供响应,这种为用户动作提供响应的机制就是事件处理. 而Android为我们提供了两套强大的响应机 ...
- cocos2d触摸事件处理机制(2.x和3.x变化)
2.x的触摸事件的版本号 触摸事件处理有2种子.以下单点触摸的样本.(另一种多点触摸屏). 创建cocos2d 该项目. 1. 重写下面虚函数. bool ccTouchBegan(cocos2d:: ...
- 【知识梳理1】Android触摸事件机制
前言 随着科学技术的发展,智能手机早已成为我们当代人身边不可缺少的"伙伴"之中的一个,堪比对象女友.每天我们对着手机反复的做着点击.滑动操作,而手机则随着我们的操作给我们展示她的精 ...
- Android事件处理机制
包括监听和回调两种机制. 1. 基于监听的事件处理: 事件监听包含三类对象,事件源,事件,事件监听器.Android的事件处理机制是一种委派式(Delegation)事件处理方式:普通组件(事件源)将 ...
- Android的两种事件处理机制
UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理. 对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事 ...
- 初识Android触摸事件传递机制
前言 今天总结的一个知识点是Andorid中View事件传递机制,也是核心知识点,相信很多开发者在面对这个问题时候会觉得困惑,另外,View的另外一个难题滑动冲突,比如在ScrollView中嵌套Li ...
随机推荐
- sql常见的面试题
1.用一条SQL语句 查询出每门课都大于80分的学生姓名 name kecheng fenshu 张三 语文 81张三 数学 75李四 语文 ...
- iBeacon行为分析
研究iBeacon也有段时间了, 总结一下这段时间对于ibeaacon行为的分析. iOS 7.0及以后的版本开始支持iBeacon. 硬件方面, iPhone4S 及以后, ipad 3代及以后, ...
- 深入理解CSS弹性盒模型flex
× 目录 [1]版本更迭 [2]display [3]基本概念[4]伸缩容器[5]伸缩项目 前面的话 CSS3引入了一种新的布局模型——flex布局.flex是flexible box的缩写,一般称之 ...
- Guava - EventBus(事件总线)
Guava在guava-libraries中为我们提供了事件总线EventBus库,它是事件发布订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计 ...
- Java提高篇(二七)-----TreeMap
TreeMap的实现是红黑树算法的实现,所以要了解TreeMap就必须对红黑树有一定的了解,其实这篇博文的名字叫做:根据红黑树的算法来分析TreeMap的实现,但是为了与Java提高篇系列博文保持一致 ...
- 为什么一定要杀掉病毒?---帮一位老师解决MyDocument.exe优盘文件夹图标病毒问题
最近一位大学老师给我抱怨了一个她遇到的烦恼,一直在纠结,生活都被打乱了,事情大概是这样的: 她的优盘里辛辛苦苦弄好备课文件,放在了优盘里,可是每次上课时,就是找不到文件.有时好多文件都被修改了,非常烦 ...
- jquery获取checkbox的值并post提交
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- EF架构~linq模拟left join的两种写法,性能差之千里!
回到目录 对于SQL左外连接我想没什么可说的,left join将左表数据都获出来,右表数据如果在左表中不存在,结果为NULL,而对于LINQ来说,要实现left join的效果,也是可以的,在进行j ...
- Liferay7 BPM门户开发之37: Liferay7下的OSGi Hook集成开发
hook开发是Liferay客制扩展的一种方式,比插件灵活,即可以扩展liferay门户,也能对原有特性进行更改,Liferay有许多内置的服务,比如用hook甚至可以覆盖Liferay服务. 可作为 ...
- Java中的数是用补码表示的检验
一.基本介绍(关于下列五个定义来自http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html#!comments,谢原 ...