返回
顶部

修改密码

android Touch事件的处理流程 android开发教程

+1

-1

收藏

+1

-1

点赞0

评论0

作 为触屏手机,触摸事件是最基本的事件,没有之一。在实际的触屏事件响应的过程中,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", "InterceptTouchEvent  A " + 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", "InterceptTouchEvent  B " + 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", "InterceptTouchEvent  C " + 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处理。

扫一扫在手机打开

评论
已有0条评论
0/150
提交
热门评论
相关推荐
今日要闻
换一批
热点排行