文档章节

Android-onInterceptTouchEvent()和onTouchEvent()

younchen
 younchen
发布于 2015/10/12 14:21
字数 2553
阅读 104
收藏 3
点赞 0
评论 0

老实说,这两个小东东实在是太麻烦了,很不好懂,我自己那api文档都头晕,在网上找到很多资料,才知道是怎么回事,这里总结一下,记住这个原则就会很清楚了:

1、onInterceptTouchEvent()是用于处理事件(类似于预处理,当然也可以不处理)并改变事件的传递方向,也就是决定是否允许Touch事件继续向下(子控件)传递,一但返回True(代表事件在当前的viewGroup中会被处理),则向下传递之路被截断(所有子控件将没有机会参与Touch事件),同时把事件传递给当前的控件的onTouchEvent()处理;返回false,则把事件交给子控件的onInterceptTouchEvent()


2、onTouchEvent()用于处理事件,返回值决定当前控件是否消费(consume)了这个事件,也就是说在当前控件在处理完Touch事件后,是否还允许Touch事件继续向上(父控件)传递,一但返回True,则父控件不用操心自己来处理Touch事件。返回true,则向上传递给父控件(注:可能你会觉得是否消费了有关系吗,反正我已经针对事件编写了处理代码?答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。)



概念介绍

1、onInterceptTouchEvent()是用于处理事件(重点onInterceptTouchEvent这个事件是从父控件开始往子控件传的,直到有拦截或者到没有这个事件的view,然后就往回从子到父控件,这次是onTouch的)(类似于预处理,当然也可以不处理)并改变事件的传递方向,也就是决定是否允许Touch事件继续向下(子控件)传递,一但返回True(代表事件在当前的viewGroup中会被处理),则向下传递之路被截断(所有子控件将没有机会参与Touch事件),同时把事件传递给当前的控件的onTouchEvent()处理;返回false,则把事件交给子控件的onInterceptTouchEvent()

 

2、onTouchEvent()用于处理事件(重点onTouch这个事件是从子控件回传到父控件的,一层层向下传),返回值决定当前控件是否消费(consume)了这个事件,也就是说在当前控件在处理完Touch事件后,是否还允许Touch事件继续向上(父控件)传递。返回false,则向上传递给父控件,详细一点就是这个touch事件就给了父控件,那么后面的up事件就是到这里touch触发,不会在传给它的子控件。如果父控件依然是false,那touch的处理就给到父控件的父控件,那么up的事件处理都在父控件的父控件,不会触发下面的。

返回true,如果是子控件返回true,那么它的touch事件都在这里处理,父控件是处理不了,因为它收不到子控件传给他的touch,被子控件给拦截了。(这里啰嗦了这么多就是为了加深记忆,这个两个事件理解起来都这么麻烦了,更何况去记,记我肯定是一下子就忘的了^0^)

(注:可能你会觉得是否消费了有关系吗,反正我已经针对事件编写了处理代码?答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。)

详细介绍

onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,Android这么设计的想法也很好理解,由于ViewGroup会包含若干childView,因此需要能够统一监控各种touch事件的机会,因此纯粹的不能包含子view的控件是没有这个方法的,如LinearLayout就有,TextView就没有。

onInterceptTouchEvent()使用也很简单,如果在ViewGroup里覆写了该方法,那么就可以对各种touch事件加以拦截。但是如何拦截,是否所有的touch事件都需要拦截则是比较复杂的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。

关于返回值的问题,基本规则很清楚,如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。


onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截.

  1. down事件首先会传递到onInterceptTouchEvent()方法

  2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。

  3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。

  4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。

  5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。


    仅仅看这个官方文档解释,就能理解清楚这两个函数关系以及用途的绝对是富有经验的framework高手。
    否则,一定需要一个案例来阐释。假设我们有这样一个layout,非常典型的


    用一个示例图来解释这个layout:


    通常外围的layoutview1,layoutview2,只是布局的容器不需要响应触屏的点击事件,仅仅Mytextview需要相应点击。但这只是一般情况,一些特殊的布局可能外围容器也要响应,甚至不让里面的mytextview去响应。更有特殊的情况是,动态更换响应对象。
    那么首先看一下默认的触屏事件的在两个函数之间的传递流程。如下图:


    如果仅仅想让MyTextView来响应触屏事件,让MyTextView的OnTouchEvent返回true,那么事件流就变成如下图,可以看到layoutview1,layoutview2已经不能进入OnTouchEvent:


    另外一种情况,就是外围容器想独自处理触屏事件,那么就应该在相应的onInterceptTouchEvent函数中返回true,表示要截获触屏事件,比如layoutview1作截获处理,处理流变成如下图:


    以此类推,我们可以得到各种具体的情况,整个layout的view类层次中都有机会截获,而且能看出来外围的容器view具有优先截获权。

    当我们去做一些相对来讲具有更复杂的触屏交互效果的应用时候,经常需要动态变更touch event的处理对象,比如launcher待机桌面和主菜单(见下图),从滑动屏幕开始到停止滑动过程当中,只有外围的容器view才可以处理touch event,否则就会误点击上面的应用图标或者widget.反之在静止不动的状态下则需要能够响应图标(子view)的touch事件。摘取framework中abslistview代码如下




    总结:

    仅仅通过概览性的官方文档是很难理解onInterceptTouchEvent函数的用途的,只有通过演绎这个抽象的规则,配以图文才能获取这个重要的知识。很显然,默认是返回false,不做截获。返回true之后,事件流的后端控件就没有机会处理touch事件了,把默认的事件流中每个处理函数看作一个节点,这个节点只要返回true, 后续的事件就被截止了,这样想就很好理解。




    onInterceptTouchEvent是在ViewGroup里面定义的。Android中的layout布局类一般都是继承此类的。onInterceptTouchEvent是用于拦截手势事件的,每个手势事件都会先调用onInterceptTouchEvent。 
    onInterceptTouchEvent()用于处理事件并改变事件的传递方向。返回值为false时事件会传递给子控件的onInterceptTouchEvent();返回值为true时事件会传递给当前控件的onTouchEvent(),而不在传递给子控件,这就是所谓的Intercept(截断)。
    onTouchEvent() 用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。可能你要问是否消费了又区别吗,反正我已经针对事件编写了处理代码?答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。

    1. public boolean onInterceptTouchEvent(MotionEvent ev) {

    2.         int action = ev.getAction();


    3.         switch (action & MotionEvent.ACTION_MASK) {

    4.         case MotionEvent.ACTION_DOWN: {

    5.  

    6.             if (touchMode == TOUCH_MODE_FLING) {

    7.                 return true;  //fling状态,截获touch,因为在滑动状态,不让子view处理

    8.             }

    9.             break;

    10.         }


    11.         case MotionEvent.ACTION_MOVE: {

    12.             switch (mTouchMode) {

    13.             case TOUCH_MODE_DOWN:

    14.                 final int pointerIndex = ev.findPointerIndex(mActivePointerId);

    15.                 final int y = (int) ev.getY(pointerIndex);

    16.                 if (startScrollIfNeeded(y - mMotionY)) {

    17.                     return true;//开始滑动状态,截获touch事件,不让子view处理

    18.                 }

    19.                 break;

    20.             }

    21.             break;

    22.         }

    23. }

    24. <com.test.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"  

    25.     android:orientation="vertical" android:layout_width="fill_parent"  

    26.     android:layout_height="fill_parent">  

    27.     <com.test.LayoutView2  

    28.         android:orientation="vertical" android:layout_width="fill_parent"  

    29.         android:layout_height="fill_parent" android:gravity="center">  

    30.         <com.test.MyTextView  

    31.             android:layout_width="wrap_content"   android:layout_height="wrap_content"  

    32.       />  

    33.     </com.test.LayoutView2>  

    34. </com.test.LayoutView1>



    ViewGroup里的onInterceptTouchEvent默认值是false这样才能把事件传给View里的onTouchEvent.

    ViewGroup里的onTouchEvent默认值是false。

    View里的onTouchEvent返回默认值是true.这样才能执行多次touch事件。


    本文转载自:http://blog.csdn.net/lvxiangan/article/details/9309927

    共有 人打赏支持
    younchen
    粉丝 8
    博文 94
    码字总数 29970
    作品 0
    延吉
    程序员
    Android Touch系统简介(二):实例详解onInterceptTouchEvent与onT

    上一篇文章主要讲述了Android的TouchEvent的分发过程,其中有两个重要的函数:onInterceptTouchEvent和onTouchEvent,这两个函数可被重装以完成特定的逻辑。onInterceptTouchEvent的定义为于...

    JayPark不作死
    2014/11/11
    0
    0
    onInterceptTouchEvent和onTouchEvent调用时序

    onInterceptTouchEvent()是ViewGroup的一个方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,Android这么设计的想法也很好理解,由于ViewG...

    yzp531
    2013/04/25
    0
    0
    Android中父View和子view的点击事件的执行过程

    Android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解。 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTIONDOWN->ACTIONMOV...

    火云
    2015/06/11
    0
    0
    Android dispatchTouchEvent介绍

    android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解。 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTIONDOWN->ACTIONMOV...

    天下杰论
    2012/12/20
    0
    0
    Android-onInterceptTouchEvent()和onTouchEvent()总结

    老实说,这两个小东东实在是太麻烦了,很不好懂,我自己那api文档都头晕,在网上找到很多资料,才知道是怎么回事,这里总结一下,记住这个原则就会很清楚了: 1、onInterceptTouchEvent()是用...

    AlexMahoneFBI
    2015/05/07
    0
    0
    android事件分发机制总结

    Android事件分发机制 在android 普通view(不包含ViewGroup)和activity中主要有一下两个方法处理事件: public boolean dispatchTouchEvent(MotionEvent ev) // 分发事件public boolean on...

    亓斌哥哥
    2014/10/08
    0
    1
    笔记KeyEvent 和 TouchEvent在 Activity和View中传递的顺序

    由于一个电视机 Key事件传递出现了部分问题,但是五位方向键有时候出现问题 所以使用Activity完全接管了key事件的传递, 自己来控制焦点的变化和五位方向键的按下处理逻辑 在此温习一下key事件...

    SuShine
    2015/08/27
    0
    0
    listview所带来的滑动冲突

    在android中,有时候会遇到子控件和父控件都要滑动的情况,尤其是当子控件为listview的时候。这种情况较常见,典型的launcher,每个屏幕上放上listview就会出现这种情况。 有两点需要注意: ...

    任玉刚
    2015/03/26
    0
    0
    android 滑动事件冲突解决 Touch事件处理机制

    android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解。 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTIONDOWN->ACTIONMOV...

    haman
    2013/11/05
    0
    0
    Android 触摸事件分发ViewGroup&View

    做笔记用,方便以后糊涂了,过来看看: 贴代码的话就太多了,但是不贴又怕以后看不明白: 子View import android.content.Context;import android.util.AttributeSet;import android.util.Lo...

    Drealin
    2013/06/19
    0
    0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    下一页

    Java设计模式学习之工厂模式

    在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

    路小磊
    18分钟前
    0
    0
    npm profile 新功能介绍

    转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

    durban
    29分钟前
    0
    0
    Serial2Ethernet Bi-redirection

    Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

    zungyiu
    35分钟前
    0
    0
    python里求解物理学上的双弹簧质能系统

    物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

    wangxuwei
    50分钟前
    0
    0
    apolloxlua 介绍

    ##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

    钟元OSS
    56分钟前
    0
    0
    Mybatis入门

    简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

    霍淇滨
    今天
    0
    0
    开发技术瓶颈期,如何突破

    前言 读书、学习的那些事情,以前我也陆续叨叨了不少,但总觉得 “学习方法” 就是一个永远在路上的话题。个人的能力、经验积累与习惯方法不尽相同,而且一篇文章甚至一本书都很难将学习方法...

    _小迷糊
    今天
    0
    0
    安装tensorflow-XXX报错

    报错: tensorflow-0.5.0-cp27-none-linux_x86_64.whl is not a supported wheel on this platform. 解决: wget https://bootstrap.pypa.io/get-pip.py sudo python2.7 get-pip.py sudo p......

    Yao--靠自己
    今天
    0
    0
    JVM学习手册(一):JVM模型

    一直从事JAVA开发,天天和JVM打交道,仔细想想对JVM还真的不是特别了解,实在是不应该.周六看了许多资料,也算有点心得,记录一下。 JVM内存模型分为5个区域:方法区,堆,虚拟机栈,本地方法栈,程序计...

    勤奋的蚂蚁
    今天
    0
    0
    转行零基础该如何学Python?这些一定要明白!

    转行零基础学Python编程开发难度大吗?从哪学起?近期很多小伙伴问我,如果自己转行学习Python,完全0基础能否学会呢?Python的难度到底有多大?今天,小编就来为大家详细解读一下这个问题。...

    猫咪编程
    今天
    2
    0

    没有更多内容

    加载失败,请刷新页面

    加载更多

    下一页

    返回顶部
    顶部