关闭

Android Touch事件传递机制解析

标签: Androidtouch
311人阅读 评论(0) 收藏 举报
分类:

声明:转载下面一片文章,不知道原创是谁


开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。

android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法:

1)public boolean dispatchTouchEvent(MotionEvent ev)          这个方法用来分发TouchEvent

2)public boolean onInterceptTouchEvent(MotionEvent ev)         这个方法用来拦截TouchEvent

3)public boolean onTouchEvent(MotionEvent ev)                 这个方法用来处理TouchEvent

注意:不是所有的View的子类,很多教程都说的是所有的View的子类,只有可以向里面添加View的控件才需要分发,比如TextView它本身就是最小的view了,所以不用再向它的子视图分发了,它也没有子视图了,所以它没有dispatch和Intercept,只有touchEvent。

 

device-2012-03-24-084959.png

说明: 白色为最外层,它占满整个屏幕;

红色为中间区域,属于白色中的一层;

黑色为中心区域,必于红色中的一层。

注意:他们本质上是:LinearLayout,而不是RelativeLayout或者其它布局。

1.由中心区域处理touch事件

布局文件如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">
        <com.kris.touch.widget.TouchView
            android:id="@+id/view_out"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#fff"
            android:gravity="center">
                <com.kris.touch.widget.TouchView
                    android:id="@+id/view_mid"
                    android:layout_width="300px"
                    android:layout_height="400px"
                    android:background="#f00"
                    android:gravity="center">
                <com.kris.touch.widget.TouchView
                    android:id="@+id/view_center"
                    android:layout_width="150px"
                    android:layout_height="150px"
                    android:background="#000"
                    android:gravity="center"
                    android:clickable="true">
                </com.kris.touch.widget.TouchView>
                </com.kris.touch.widget.TouchView>
        </com.kris.touch.widget.TouchView>
    </LinearLayout>


注意:                android:clickable="true"  

接下来我们看一下打印的日志:

1111.png

结合是上面的日志,我们可以看一下ACTION_DOWN事件处理流程:

a0dfaa98gb7f95585f7a2&690.png

说明:

首先触摸事件发生时(ACTION_DOWN),由系统调用Activity的dispatchTouchEvent方法,分发该事件。根据触摸事件的坐标,将此事件传递给out的dispatchTouchEvent处理,out则调用onInterceptTouchEvent 判断事件是由自己处理,还是继续分发给子View。此处由于out不处理Touch事件,故根据事件发生坐标,将事件传递给out的直接子View(即middle)。

Middle及Center中事件处理过程同上。但是由于Center组件是clickable 表示其能处理Touch事件,故center中的onInterceptTouchEvent方法将事件传递给center自己的onTouchEvent方法处理。至此,此Touch事件已被处理,不继续进行传递。

2.没有指定谁会处理touch事件

布局文件如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">
        <com.kris.touch.widget.TouchView
            android:id="@+id/view_out"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#fff"
            android:gravity="center">
                <com.kris.touch.widget.TouchView
                    android:id="@+id/view_mid"
                    android:layout_width="300px"
                    android:layout_height="400px"
                    android:background="#f00"
                    android:gravity="center">
                <com.kris.touch.widget.TouchView
                    android:id="@+id/view_center"
                    android:layout_width="150px"
                    android:layout_height="150px"
                    android:background="#000"
                    android:gravity="center">
                </com.kris.touch.widget.TouchView>
                </com.kris.touch.widget.TouchView>
        </com.kris.touch.widget.TouchView>
    </LinearLayout>

注意:只是比上一次的布局少了android:clickable="true"
接下来我们看一下打印的日志

2222.png

结合是上面的日志,我们可以看一下ACTION_DOWN事件处理流程:

a0dfaa98gb7f9559d8155&690.png

说明:

事件处理流程大致同上,区别是此状态下,所有组件都不会处理事件,事件并不会被center的onTouchEvent方法“消费”,则事件会层层逆向传递回到Activity,若Activity也不对此事件进行处理,此事件相当于消失了(无效果)。

对于后续的move、up事件,由于第一个down事件已经确定由Activity处理事件,故up事有由Activity的dispatchTouchEvent直接分发给自己的onTouchEvent方法处理。

代码请看最后的附件

总结:

1) Touchevent 中,返回值是 true ,则说明消耗掉了这个事件,返回值是 false ,则没有消耗掉,会继续传递下去,这个是最基本的。2) 事件传递的两种方式:
隧道方式:从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递。
冒泡方式:从最内层子元素依次往外传递直到根元素或在中间某一元素中由于某一条件停止传递。 android对Touch Event的分发逻辑是View从上层分发到下层(dispatchTouchEvent函数)类似于隧道方式,然后下层优先开始处理Event(先mOnTouchListener,再onTouchEvent)并向上返回处理情况(boolean值),若返回true,则上层不再处理。类似于冒泡方式
于是难题出现了,你若把Touch Event都想办法给传到上层了(只能通过返回false来传到上层),那么下层的各种子View就不能处理后续事件了。而有的时候我们需要在下层和上层都处理Touch事件

举个例子,ViewFlipper用来检测手势,在内部我们放几个Image,有点像gallery的效果,也就是左右滑动切换图片,但是图片有时候我们希望可以放大缩小!这样就会存在ViewFlipper里面需要touch事件,而在image里面也需要一个touch事件(当图片大小屏幕边界的时候可以拖动图片,而不是左右切换图片)。

我首先的思路是着手于事件回传的方式,研究了n久,实际了n久,都没达到自己想要的结果 ,我甚至于把gallery和gallery3D 的源码下载下来看了N久也没办法去解决,在这里随便说一下gallery吧,gallery虽然在这个效果,但是人家并不是ViewFlipper加image这样来实现的,人家是像游戏这样用一个view来统一处理的,我们可以简单的理解成自定义了一个控件,这样touch事件想怎么处理就怎么处理,不过就是逻辑复杂了,我们想偷懒就没办法了,呵呵。。。

最后不停的试啊试啊,想到一个可行的方案,但是我觉得不是很靠谱,也就是:我们在ViewFlipper这里,我们先把所有的touch都截取到,然后在他的onTouchEvent中,我们先调用imageview的onTouchEvent事件,如果返回true,证明这个事件,imageview要用,那么ViewFlipper就当什么事都没发生,如果imageview返回的false,则调用自己的touchEvent.伪代码如下:

  1. //自定义一个MyViewFlipper 继承于ViewFlipper,并且实现onTouchEvent方式,

复制代码

我觉得他不靠谱的原因为: 1. 他打断了android的原有的机制,不是很提倡。
2. 得试先知道ViewFlipper里面的控件,或者说通过某种路径能获取到
3. 如果ViewFlipper里面的控件多了,就蛋疼了

0
0
查看评论

Android Touch事件传递机制全面解析(从WMS到View树)

转眼间近一年没更新博客了,工作一忙起来,很难有时间来写博客了,由于现在也在从事Android开发相关的工作,因此以后的博文也会更多地专注于这一块。 这篇文章准备从源码层面为大家带来Touch事件的传递机制,我这里分析的源码时Android4.4的。说到分析源码,光看肯定是不行的,一定要亲自去跟,并...
  • mmc_maodun
  • mmc_maodun
  • 2015-12-21 07:43
  • 8358

android Touch事件传递机制解析

在讲正题之前我们讲一段有关任务传递的小故事,抛砖迎玉下: 话说一家软件公司,来一个任务,分派给了开发经理去完成: 开发经理拿到,看了一下,感觉好简单,于是 开发经理:分派给了开发组长 开发组长:分派给了自己组员(程序员) 程序员:分派给了自己带的实习生。 实习生:好苦逼,无法分派,怎...
  • xujie1991618
  • xujie1991618
  • 2015-06-23 17:08
  • 375

Android Touch事件传递机制解析

Android Touch事件传递机制解析 没事逛论坛,无意间看到了一篇非常不错的帖子,转载如下:   开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。 android系统中的每个ViewGro...
  • tigriswing
  • tigriswing
  • 2014-07-01 20:10
  • 320

Android-三张图搞定Touch事件传递机制

上图之前先讲下Android事件的基础知识:1.所有的Touch事件都封装到MotionEvent里面2.事件处理包括三种情况,分别为:传递—-dispatchTouchEvent()函数、拦截——onInterceptTouchEvent()函数、消费—-onTouchEvent()函数和OnTo...
  • Bond_zhe
  • Bond_zhe
  • 2016-08-13 18:27
  • 441

彻底掌握Android的Touch触摸事件传递机制

目录 一、Touch基本知识 二、Android事件传递流程: 流程图胜千言 流程图原理,对流程图的具体解释: 三、如何写自定义touch事件: 处理一个手指: 处理多个手指: 四、常用的系统的处理触摸事件: 五、手势委派 一、 Touch基本知识 1. 所有的T...
  • a_long_
  • a_long_
  • 2016-08-05 00:11
  • 2844

Android中Touch事件传递机制解析

开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。 android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatch...
  • qq_33729889
  • qq_33729889
  • 2017-03-12 10:14
  • 97

Android Touch事件传递机制解析 X2

MotionEvent事件在onInterceptTouchEvent()、onTouchEvent()中的传递顺序  onInterceptTouchEvent()用于处理事件并改变事件的传递方向。处理事件这个不用说了,你在函数内部编写代码处理就可以了。而决定传递方向的是返回值,返...
  • jhydn
  • jhydn
  • 2014-01-17 12:11
  • 388

Android Touch事件传递机制解析+demo

开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。 android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatch...
  • android_panda
  • android_panda
  • 2014-03-14 17:32
  • 591

Android Touch事件传递机制解析(一)

开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。 android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean di...
  • xiangjai
  • xiangjai
  • 2013-01-24 13:36
  • 754

Touch事件传递机制解析

dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent
  • cai_iac
  • cai_iac
  • 2017-03-01 16:49
  • 421
    个人资料
    • 访问:537600次
    • 积分:8159
    • 等级:
    • 排名:第2997名
    • 原创:297篇
    • 转载:39篇
    • 译文:0篇
    • 评论:104条
    坚持不懈
    如果这篇文章帮助了你,可以点入下面的连接,帮忙点击两个广告,给点鼓励,Thanks♪(・ω・)ノ !!!
    VR次元
    最新评论