Android 触摸响应处理逻辑
来源:互联网 发布:家庭预算软件 编辑:程序博客网 时间:2024/05/16 04:51
一、触摸响应逻辑概述
1.用户一个点击屏幕的动作会产生下面一系列触摸事件 :
1)public boolean dispatchTouchEvent(MotionEvent ev)
2)public boolean onInterceptTouchEvent(MotionEvent ev)
3)public boolean onTouchEvent(MotionEvent ev)
onInterceptTouchEvent() 用于处理事件并改变事件的传递方向。返回值为false时事件会传递给子控件的onInterceptTouchEvent();返回值为true时事件会传递给当前控件的onTouchEvent(),而不在传递给子控件,这就是所谓的Intercept(截断)。
onTouchEvent() 用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。可能你要问是否消费了又区别吗,反正我已经针对事件编写了处理代码?答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。
1)触摸事件被驱动上报给android的wms(windowsmanagerservice);
2)wms将这些触摸事件分发给当前活动的Activity;
3)当前活动的Activity拿到事件,调用VIewRoot类的dispatchTouchEvent,给当前活动窗口的根view;
4)根view按照从下到上的顺序调用他的dispatchTouchEvent方法把事件到子view;
5)每个view有一个方法onInterceptTouchEvent,可以拦截触摸事件,返回true则不再继续向上传递触摸事件;
6)分发到最上层的view后,会调用他的OnTouchEvent方法,然后按照从上到下的顺序调用下一层view的OnTouchEvent方法;
7)如果某层的view的OnTouchEvent方法返回true,就中断传递触摸事件,不再调用下一层view的OnTouchEvent方法。
这样的触摸事件处理逻辑使得每一层的view都有机会响应触摸消息,非常的灵活。
二、示例说明
还是拿一个Activity举例说明,如下图所示:
附上xml文件:
- <com.test.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <com.test.LayoutView2
- android:orientation="vertical" android:layout_width="fill_parent"
- android:layout_height="fill_parent" android:gravity="center">
- <com.test.MyTextView
- android:layout_width="wrap_content" android:layout_height="wrap_content"
- />
- </com.test.LayoutView2>
- </com.test.LayoutView1>
这个activity里面从下到上的view有:LayoutView1、LayoutView2、MyTxtView
那么首先看一下默认的触屏事件的在onInterceptTouchEvent 、onTouchEvent两个函数之间的传递流程。如下图:
如果仅仅想让MyTextView来响应触屏事件,让MyTextView的OnTouchEvent返回true,那么事件流就变成如下图,可以看到layoutview1,layoutview2已经不能进入OnTouchEvent:
另外一种情况,就是外围容器想独自处理触屏事件,那么就应该在相应的onInterceptTouchEvent函数中返回true,表示要截获触屏事件,比如layoutview1作截获处理,处理流变成如下图:
以此类推,我们可以得到各种具体的情况,整个layout的view类层次中都有机会截获,而且能看出来外围的容器view具有优先截获权。
当然,通常外围的layoutview1,layoutview2,只是布局的容器不需要响应触屏的点击事件,仅仅Mytextview需要相应点击。但这只是一般情况,一些特殊的布局可能外围容器也要响应,甚至不让里面的mytextview去响应。更有特殊的情况是,动态更换响应对象。
三、多层次动态处理触摸事件
当我们去做一些相对来讲具有更复杂的触屏交互效果的应用时候,经常需要动态变更touch event的处理对象,比如launcher待机桌面和主菜单(见下图),从滑动屏幕开始到停止滑动过程当中,只有外围的容器view才可以处理touch event,否则就会误点击上面的应用图标或者widget.反之在静止不动的状态下则需要能够响应图标(子view)的touch事件。摘取framework中abslistview代码如下
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN: {
-
- if (touchMode == TOUCH_MODE_FLING) {
- return true; //fling状态,截获touch,因为在滑动状态,不让子view处理
- }
- break;
- }
- case MotionEvent.ACTION_MOVE: {
- switch (mTouchMode) {
- case TOUCH_MODE_DOWN:
- final int pointerIndex = ev.findPointerIndex(mActivePointerId);
- final int y = (int) ev.getY(pointerIndex);
- if (startScrollIfNeeded(y - mMotionY)) {
- return true;//开始滑动状态,截获touch事件,不让子view处理
- }
- break;
- }
- break;
- }
- }
四、 运用
前几天我需要实现一个功能:点击屏幕任意区域挂断通话并退出窗口,直接实现方法dispatchTouchEvent即可:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
Log.d(TAG,"test-- monitor dispatchTouchEvent!");
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
SystemServer.hangUp(CallId);
break;
}
return super.dispatchTouchEvent(ev);
}
- Android 触摸响应处理逻辑
- android触摸事件处理逻辑
- android触摸响应传递机制
- Windows 触摸操作的响应及处理
- Android:处理触摸事件
- Android 触摸消息处理
- Android 触摸OnTouchListener没有响应问题解决
- Android触摸事件分发与响应
- [Android]View响应屏幕触摸事件
- android的触摸事件处理
- android触摸事件处理流程
- android触摸事件处理流程
- Android 触摸事件处理机制
- Android多点触摸交互处理
- Android 触摸事件处理机制
- Android点击触摸时间处理
- Android多点触摸交互处理
- Android多点触摸交互处理
- IOs动态调整 UITableViewCell的高度
- cocos2d-x自带的CCHttpClient下载百度网页并写入成网页文件
- vi/vim 基本使用方法
- servlet中参数的传递方式
- 单例设计模式
- Android 触摸响应处理逻辑
- 使用JAXB处理JavaBean和XML的转换
- apache -tomcat 负载均衡 --只为学习
- 正则表达式 实例
- Three20学习之清空网络缓存
- 拿到现成的wsdl. 用java开发webService服务端
- 关于MYSQL 更改表引擎的文章
- ByteArrayOutputStream用法
- 解决cast from 'char*' to 'char**' increases required alignment of target type [-Werror=cast-align]