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 触摸事件处理机制的更多相关文章

  1. Android的事件处理机制详解(二)-----基于监听的事件处理机制

    基于监听的事件处理机制 前言: 我们开发的app更多的时候是需要与用户的交互----即对用户的操作进行响应 这就涉及到了android的事件处理机制; android给我们提供了两套功能强大的处理机制 ...

  2. Android的事件处理机制(一)------基于回调机制的事件处理

    Android平台的事件处理机制有两种,一种是基于回调机制的,一种是基于监听接口的,现介绍第一种:基于回调机制的事件处理.Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通 ...

  3. Android的事件处理机制之基于回调的事件处理

    回调机制 如果说事件监听机制是一种委托式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源与事件监听器是统一的,换种方法说事件监听器完全消失了,当用户在GUI组件上激发某个事件 ...

  4. Android的事件处理机制之基于监听的事件处理

    无论是桌面应用还是手机应用程序,面对用户的使用,经常需要处理的便是用户的各种动作,也就是需要为用户动作提供响应,这种为用户动作提供响应的机制就是事件处理. 而Android为我们提供了两套强大的响应机 ...

  5. cocos2d触摸事件处理机制(2.x和3.x变化)

    2.x的触摸事件的版本号 触摸事件处理有2种子.以下单点触摸的样本.(另一种多点触摸屏). 创建cocos2d 该项目. 1. 重写下面虚函数. bool ccTouchBegan(cocos2d:: ...

  6. 【知识梳理1】Android触摸事件机制

    前言 随着科学技术的发展,智能手机早已成为我们当代人身边不可缺少的"伙伴"之中的一个,堪比对象女友.每天我们对着手机反复的做着点击.滑动操作,而手机则随着我们的操作给我们展示她的精 ...

  7. Android事件处理机制

    包括监听和回调两种机制. 1. 基于监听的事件处理: 事件监听包含三类对象,事件源,事件,事件监听器.Android的事件处理机制是一种委派式(Delegation)事件处理方式:普通组件(事件源)将 ...

  8. Android的两种事件处理机制

    UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理. 对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事 ...

  9. 初识Android触摸事件传递机制

    前言 今天总结的一个知识点是Andorid中View事件传递机制,也是核心知识点,相信很多开发者在面对这个问题时候会觉得困惑,另外,View的另外一个难题滑动冲突,比如在ScrollView中嵌套Li ...

随机推荐

  1. 12G服务器在BIOS中收集阵列卡日志(TTY日志)的方法

      如果系统进不去.请参考如下方法收集日志. 请准备个U 盘,容量在8G以下(含8G),否则会识别不到. 图片参考,以描述为准 F2 enter BIOS option--> Enter the ...

  2. markdown语法记录

    换行:在结尾加两个空格后回车. 缩进:将输入法切换到全角,两个空格就是两个汉字的大小.

  3. 直接代码POST数据调用WebService

    ps:使用过webservice的童鞋大概都明白它是基于Soap协议交换数据的,同时Soap协议是对HTTP协议的扩展,其实我们就可以认为调用一个WEB服务就是通过http协议GET或POST数据的过 ...

  4. 【Win10 UWP】QQ SDK(二):SDK的回调处理

    上一讲,我们介绍了QQ SDK的使用方法,请看<[Win10 UWP]QQ SDK(一):SDK基本使用方法> 一. 回调的基本形式 从前面的介绍中我们知道,我们的应用和QQ客户端之间需要 ...

  5. Jexus V5.8.0正式发布:跨平台的ASP.NET WEB服务器

    Jexus Web Server V5.8.0 已于今日(12月10日)正式发布,下载地址:http://www.linuxdot.net/. Jexus v5.8.0有如下的更新: 1,为反向代理增 ...

  6. 【腾讯Bugly干货分享】React移动web极致优化

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/579083d1c9da73584b02587d 最近一个季度,我们都在为手Q家校 ...

  7. Java多线程9:ThreadLocal源码剖析

    ThreadLocal源码剖析 ThreadLocal其实比较简单,因为类里就三个public方法:set(T value).get().remove().先剖析源码清楚地知道ThreadLocal是 ...

  8. .net开发笔记(十二) 设计时与运行时的区别(续)

    上一篇博客详细讲到了设计时(DesignTime)和运行时(RunTime)的概念与区别,不过没有给出实际的Demo,今天整理了一下,做了一个例子,贴出来分享一下,巩固前一篇博客讲到的内容. 简单回顾 ...

  9. ASP.NET一般处理程序访问Session问题

    我们在使用一般处理程序的时候,访问Session会出现如下错误: 解决方案如下: //引用命名空间 using System.Web.SessionState; //继承IRequiresSessio ...

  10. ACEXML解析XML文件——简单示例程序

    掌握了ACMXML库解析XML文件的方法后,下面来实现一个比较完整的程序. 定义基本结构 xml文件格式如下 <?xml version="1.0"?> <roo ...