android 事件处理机制之requestDisallowInterceptTouchEvent
当手指触摸到屏幕时,系统就会调用相应View的onTouchEvent,并传入一系列的action。当有多个层级的View时,在父层级允许的情 况下,这个action会一直向下传递直到遇到最深层的View。所以touch事件最先调用的是最底层View的onTouchEent,如果View 的onTouchEvent接收到某个touch action并作了相应处理,最后有两种返回方式return true和return false;return true会告诉系统当前的View需要处理这次的touch事件,以后的系统发出的ACTION_MOVE,ACTION_UP还是需要继续监听并接收 的,而且这次的action已经被处理掉了,父层的View是不可能出发onTouchEvent了。所以每一个action最多只能有一个 onTouchEvent接口返回true。如果return false,便会通知系统,当前View不关心这一次的touch事件,此时这个action会传向父级,调用父级View的onTouchEvent。 但是这一次的touch事件之后发出的任何action,该View都不会再接受,onTouchEvent在这一次的touch事件中再也不会触发,也 就是说一旦View返回false,那么之后的ACTION_MOVE,ACTION_UP等ACTION就不会在传入这个View,但是下一次 touch事件的action还是会传进来的。
前面说了底层的View能够接收到这次的事件有一个前提条件:在父层级允许的情况下。假设不改变父层级的dispatch方法,在系统调用底层
onTouchEvent之前会先调用父View的onInterceptTouchEvent方法判断,父层View是不是要截获本次touch事件之
后的action。如果onInterceptTouchEvent返回了true,那么本次touch事件之后的所有action都不会再向深层的
View传递,统统都会传给负层View的onTouchEvent,就是说父层已经截获了这次touch事件,之后的action也不必询问
onInterceptTouchEvent,在这次的touch事件之后发出的action时onInterceptTouchEvent不会再次调
用,知道下一次touch事件的来临。如果onInterceptTouchEvent返回false,那么本次action将发送给更深层的View,
并且之后的每一次action都会询问父层的onInterceptTouchEvent需不需要截获本次touch事件。只有ViewGroup才有
onInterceptTouchEvent方法,因为一个普通的View肯定是位于最深层的View,touch事件能够传到这里已经是最后一站了,肯
定会调用View的onTouchEvent。
对于底层的View来说,有一种方法可以阻止父层的View截获touch事件,就是调用
getParent().requestDisallowInterceptTouchEvent(true);方法。一旦底层View收到touch的
action后调用这个方法那么父层View就不会再调用onInterceptTouchEvent了,也无法截获以后的action。
用例子总结一下onInterceptTouchEvent和onTouchEvent的调用顺序:
假设最高层View叫OuterLayout,中间层View叫InnerLayout,最底层View叫MyVIew。调用顺序是这样的(假设各个函数返回的都是false)
OuterLayout.onInterceptTouchEvent->InnerLayout.onInterceptTouchEvent->MyView.onTouchEvent->InnerLayout.onTouchEvent->OuterLayout.onTouchEvent。
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- getParent().requestDisallowInterceptTouchEvent(true);
- return super.dispatchTouchEvent(ev);
- }
这句话是告诉父view,我的事件自己处理
- public boolean onTouch(View v, MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_MOVE:
- pager.requestDisallowInterceptTouchEvent(true);
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- pager.requestDisallowInterceptTouchEvent(false);
- break;
- }
- }
也可以写成类似于上面那样,当用户按下的时候,我们告诉父组件,不要拦截我的事件(这个时候子组件是可以正常响应事件的),拿起之后就会告诉父组件可以阻止。
还有一个关于子控件和父控件的事件响应问题
当父控件中有子控件的时候,并且父控件和子空间都有事件处理(比如单击事件)。这时,点击子控件,父控件的单击事件就无效了。
比如一个LinearLayout里面有一个子控件TextView,但是TextView的大小没有LinearLayout大
①如果LinearLayout和TextView都设置了单击事件,那么
- 点击TextView区域的时候,触发的是TextView的事件,
- 点击TextView以外的区域的时候,还是触发的LinearLayout的事件。
②如果LinearLayout设置了单击事件,而TextView没有设置单击事件的话,那么
- 不管单击的是TextView区域,还是TextView以外的区域,都是触发的LinearLayout的单击事件
如果LinearLayout的大小和TextView一样的话,那么
①如果LinearLayout和TextView都设置了单击事件,那么
- 只有TextView的单击事件有效
②如果LinearLayout设置了单击事件,而TextView没有设置单击事件的话,那么
触发的是LinearLayout的单击事件
android 事件处理机制之requestDisallowInterceptTouchEvent的更多相关文章
- Android事件处理机制
包括监听和回调两种机制. 1. 基于监听的事件处理: 事件监听包含三类对象,事件源,事件,事件监听器.Android的事件处理机制是一种委派式(Delegation)事件处理方式:普通组件(事件源)将 ...
- Android的两种事件处理机制
UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理. 对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事 ...
- Android的Touch事件处理机制
Android的Touch事件处理机制比较复杂,特别是在考虑了多点触摸以及事件拦截之后. Android的Touch事件处理分3个层面:Activity层,ViewGroup层,View层. 首先说一 ...
- Android的事件处理机制详解(二)-----基于监听的事件处理机制
基于监听的事件处理机制 前言: 我们开发的app更多的时候是需要与用户的交互----即对用户的操作进行响应 这就涉及到了android的事件处理机制; android给我们提供了两套功能强大的处理机制 ...
- Android的事件处理机制(一)------基于回调机制的事件处理
Android平台的事件处理机制有两种,一种是基于回调机制的,一种是基于监听接口的,现介绍第一种:基于回调机制的事件处理.Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通 ...
- Android平台的事件处理机制和手指滑动例子
Android平台的事件处理机制有两种 基于回调机制的事件处理:Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通过重写View中的这些回调方法来实现需要的响应事件. 基于 ...
- Android——事件处理模型一(基于回调机制的事件处理)(转)
Android平台的事件处理机制有两种,一种是基于回调机制的,一种是基于监听接口的,现介绍第一种:基于回调机制的事件处理.Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通 ...
- Android基础新手教程——3.1 基于监听的事件处理机制
Android基础新手教程--3.1.1 基于监听的事件处理机制 标签(空格分隔): Android基础新手教程 本节引言: 第二章我们学习的是Android的UI控件,我们能够利用这些控件构成一个精 ...
- Android的事件处理机制之基于回调的事件处理
回调机制 如果说事件监听机制是一种委托式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源与事件监听器是统一的,换种方法说事件监听器完全消失了,当用户在GUI组件上激发某个事件 ...
随机推荐
- mongodb维护常用命令
一,用户操作:1. #进入数据库adminuse admin2. #增加或修改用户密码db.addUser('name','pwd')3. #查看用户列表db.system.users.find()4 ...
- Kerberos的组件和术语(翻译和注解)
之所以要翻译这篇文章,是因为提到了一些通常于对Kerberos协议简介性质的文章所没有提到的细节,而这些细节对于理解Kerberos的工作原理,以及Kerberos协议实现的使用都是很有必要的. 1. ...
- javascript实现数据结构与算法系列:队列 -- 链队列和循环队列实现及示例
1 队列的基本概念 队列(Queue):也是运算受限的线性表.是一种先进先出(First In First Out ,简称FIFO)的线性表.只允许在表的一端进行插入,而在另一端进行删除. 队首(fr ...
- Unity3D研究院之LZMA压缩文件与解压文件
原地址:http://www.xuanyusong.com/archives/3095 前两天有朋友告诉我Unity的Assetbundle是LZMA压缩的,刚好今天有时间那么就研究研究LZMA.它是 ...
- CSLight研究院之学习笔记结合NGUI(一)
原地址:http://www.xuanyusong.com/archives/3088 这两天一直在研究CSLight,目前Unity热更新的方式有两种,一种是ulua这个网上的例子已经很多了.还有一 ...
- Sql注入一种dump所有数据的方法
Select exp(~(select*from(select(concat(@:=0,(select count(*)from`information_schema`.columns where t ...
- ASP.NET MVC 3和Razor中的@helper 语法
原文:http://kb.cnblogs.com/page/102191/ ASP.NET MVC 3支持一项名为"Razor"的新视图引擎选项(除了继续支持/加强现有的.aspx ...
- HDU 2048 神、上帝以及老天爷(递归,错排,dp,概率)
中文题,错排,求概率,不解释,核心思路同 HDU 1465 错排简单思路可看:http://www.cnblogs.com/laiba2004/p/3235934.html //错排,但是我之前叫了几 ...
- POJ 2141
#include<iostream> #include<stdio.h> using namespace std; int main() { //freopen("1 ...
- C#中String跟string的“区别”
string是c#中的类,String是.net Framework的类(在C# IDE中不会显示蓝色) C# string映射为.net Framework的String 如果用string,编译器 ...