展会信息港展会大全

android Touch事件的处理流程 android开发教程
来源:互联网   发布日期:2015-09-29 10:31:11   浏览:1222次  

导读:作 为触屏手机,触摸事件是最基本的事件,没有之一。在实际的触屏事件响应的过程中,public boolean onInterceptTouchEvent(MotionEvent ev)和public boolean onTouchEvent(MotionEvent event)是最重要的......

作 为触屏手机,触摸事件是最基本的事件,没有之一。在实际的触屏事件响应的过程中,public boolean onInterceptTouchEvent(MotionEvent ev)和public boolean onTouchEvent(MotionEvent event)是最重要的两个函数。下面将通过代码来展示一次触摸事件的处理流程,一次完整的触摸包括DOWN,MOVE,UP。

首先,先说下public boolean onInterceptTouchEvent(MotionEvent ev)这个函数,官方文档就不贴在这了,因为即使是官方文档其说明也是很复杂的,这里先只说总结性的一句话,onInterceptTouchEvent本身不会消耗任何触摸事件,只能影响touch事件的处理顺序,touch事件在被onTouchEvent返回true表示消耗之前会一直传递下去。当viewGroup收到触摸事件时,onInterceptTouchEvent会在onTouchEvent之前被调用,onInterceptTouchEvent的返回值决定了触摸事件是否立即被viewGroup本身的onTouchEvent响应。具体看下面。

首先自定义三个layout,ALayout,BLayout,CLayout均继承自RelativeLayout。,其中在相关函数中打印出日志:

ALayout

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

// TODO Auto-generated method stub

Log.e("sssssssssssssssss", "InterceptTouchEventA " + Common.getAction(ev));

return false;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

// TODO Auto-generated method stub

Log.e("sssssssssssssssss", "onTouchEvent A" + Common.getAction(event) );

return false;

}

BLayout

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

// TODO Auto-generated method stub

Log.e("sssssssssssssssss", "InterceptTouchEventB " + Common.getAction(ev));

return false;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

// TODO Auto-generated method stub

Log.e("sssssssssssssssss", "onTouchEvent B" + Common.getAction(event) );

return false;

}

CLayout

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

// TODO Auto-generated method stub

Log.e("sssssssssssssssss", "InterceptTouchEventC " + Common.getAction(ev));

return false;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

// TODO Auto-generated method stub

Log.e("sssssssssssssssss", "onTouchEvent C" + Common.getAction(event) );

return false;

}

下面的是布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity" >

<com.example.testaaaa.ALayout

android:id="@+id/aa"

android:layout_width="200dip"

android:layout_height="200dip"

android:layout_alignParentLeft="true"

android:layout_alignParentTop="true"

android:layout_marginLeft="61dp"

android:layout_marginTop="68dp"

android:background="#ff0000ff" >

<com.example.testaaaa.BLayout

android:id="@+id/bb"

android:layout_width="150dip"

android:layout_height="150dip"

android:layout_centerHorizontal="true"

android:layout_centerVertical="true"

android:background="#ffff0000" >

</com.example.testaaaa.BLayout>

</com.example.testaaaa.ALayout>

<com.example.testaaaa.CLayout

android:id="@+id/cc"

android:layout_width="100dip"

android:layout_height="100dip"

android:layout_centerHorizontal="true"

android:layout_centerVertical="true"

android:background="#ff00ff00" >

</com.example.testaaaa.CLayout>

</RelativeLayout>

具体就是这个样子:

结合xml中的布局可知,AB是层级或者父子关系,AC是平级或者兄弟关系。下面先点击 1 区域,打印出的日志如下:

整个流程是这样的:因为AB是层级关系,事件优先被下 发到A的onInterceptTouchEvent中,因为其返回值为false,因此A的onTouchEvent不会被立即调用,然后触摸事件继续 下发到B中,B的onInterceptTouchEvent被调用,因为其也返回false,触摸事件应该继续下发给B的子视图,但是B没有 childView,于是B的onTouchEvent被调用,又因其返回false表明事件没有被消耗,于是A的onTouchEvent被调用。(PS:下面的所有的实验都是在ABC相关函数都是返回false的基础上修改,每次都并且只修改一个值)

实验1:同样点击 1 区域,A的onInterceptTouchEvent中返回true,此时B的onInterceptTouchEvent和onTouchEvent都不会被调用

实验2:同样点击 1 区域,A的onTouchEvent返回true

实验3:同样点击 1 区域,B的onTouchEvent返回true,此时A的onTouchEvent不会被调用。

下面将ABC中onInterceptTouchEvent和onTouchEvent都返回false。这次点击 3 区域,日志如下:

这次的流程是这样的:AC为平级关系,因为C是盖在A上的,因此触摸事件先被下发到C中,C的onInterceptTouchEvent和onTouchEvent被调用,因为C中onTouchEvent返回false,因此触摸事件没有被消耗并继续被下发到A

实验4:同样点击 3 区域,但是C中onInterceptTouchEvent返回true,因为C没有childView因此不会有变化

实验6:同样点击 3 区域,但是C中onTouchEvent返回true,因为事件被C消耗,A中onInterceptTouchEvent和onTouchEvent不会被调用。

实验7:同样点击 3 区域,但是A中onTouchEvent返回true

下面将ABC中onInterceptTouchEvent和onTouchEvent都返回false。这次点击 2 区域,如果已经对touch事件的处理过程有了一定认识后,应该可以直接分析出吧。下图:

这个只是综合区域 1 和 3 的情形。

Touch事件的处理流程:

1.一旦某个ViewGroup获得了ACTION_DOWN的事件,会根据深度优先的算法遍历以该ViewGroup为根节点的view树

2.如果点击的位置在被遍历到的childView区域中,childView是groupview的话其onInterceptTouchEvent将被调用,这个过程会一直进行下去

3.直到某个viewX的onInterceptTouchEvent返回了true,或者一直遍历到某个叶viewX,然后该viewX的onTouchEvent被调用

4.如果viewX的onTouchEvent返回false,则该viewX的父节点viewY的onTouchEvent被调用,这个过程会一直下去

5.如果直到根节点的onTouchEvent都返回false,那么后续的ACTION_MOVE和ACTION_UP将被这棵树里面的所有的view忽略

6.当某个viewX在onTouchEvent中返回true后,ACTION_MOVE和ACTION_UP会从根节点开始按照深度优先的算法依次调用onInterceptTouchEvent,但是和ACTION_DOWN不同,该过程只持续到viewX的父节点为止,然后viewX的onInterceptTouchEvent不被调用,而直接调用onTouchEvent(查看实验3的日志)

7.如果在ACTION_MOVE或者ACTION_UP在被viewX的onTouchEvent处理之前,某个viewZ的onInterceptTouchEvent返回true,表明viewZ要处理接下来的触摸事件,那么在viewZ的onTouchEvent被调用之前,onInterceptTouchEvent调用还会继续下去,只不过之后的view的onInterceptTouchEvent中的ACTION变成了ACTION_CANCEL,直到viewX中的onTouchEvent处理了这个ACTION_CANCEL后,viewZ的onTouchEvent才被调用,后续事件将只被viewZ的onTouchEvent处理。

赞助本站

人工智能实验室

相关热词: Touch 事件

AiLab云推荐
推荐内容
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港