View事件传递 touch事件分发
来源:互联网 发布:淘宝主页代码装修 编辑:程序博客网 时间:2024/04/25 06:21
学习Android一年有余,今天开始以自己的理解去介绍一下Android开发常用到的基础技术。第一个介绍的是View 的事件传递机制,建议首先去看一下[codeKK中关于View事件传递介绍的文章][1],我这里只是对这个的补充以及自己理解。有不正确的地方欢迎拍砖☺。
第一部分:知识储备
- 在Android中所有的TouchEvent事件都封装在MotionEvent对象中,而TouchEvent事件主要包括Touch的位置,时间,历史记录,滑动等等。
- 常见MotionEvent的类型包括:ACTION_DOWN,ACTION_MOVE,ACTION_CANCEL,ACTION_UP,ACTION_SCROLL等等。
- 我们关心的对事件的处理实质上就是dispatchTouchEvent,onTouchEvent,onInterceptTouchEvent这三个函数,分别代表事件传递,事件消费和事件拦截的意思,这三个函数都是boolean类型的,如果返回值为true代表该事件被消耗。
(注明:以上的内容是从codeKK文章中部分摘取的)
第二部分:实战演练
以我的理解,要掌握整个事件的传递过程,必须得理清楚那三个事件处理函数,最好是自己写写代码验证一下。
以下我根据事件的消耗分四个部分:不拦截不消费,不拦截消费,拦截不消费,拦截消费。为了更好的理解,假设布局层次如下:
这个是在UI Automator中的截图,布局很简单,最外层为一个LinearLayout,然后嵌套了两个LinearLayout。在这个里为了方便我简称为从最外到里分别为L0,L1,L2。其预览图如下:
布局文件如下:
<?xml version="1.0" encoding="utf-8"?><com.example.TouchEventDemo.MyLinearLayout0 xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/L0" android:background="@android:color/white" > <com.example.TouchEventDemo.MyLinearLayout1 android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/L1" android:layout_margin="20dp" android:background="@android:color/holo_blue_dark" > <com.example.TouchEventDemo.MyLinearLayout2 android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/L2" android:background="@android:color/holo_red_light" android:layout_margin="20dp" android:orientation="horizontal" /> </com.example.TouchEventDemo.MyLinearLayout1></com.example.TouchEventDemo.MyLinearLayout0>
这里为了更好的看清楚事件的传递,我们需要自定义三个LinearLayout,并重写三个事件函数,dispatchTouchEvent,onTouchEvent,onInterceptTouchEvent
@Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i(TAG, "MyLinearLayout0------------dispatchTouchEvent"); return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i(TAG, "MyLinearLayout0------------onTouchEvent"); return super.onTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i(TAG, "MyLinearLayout0------------onInterceptTouchEvent"); return super.onInterceptTouchEvent(ev); }
好了,前期准备工作已经完成,我们开始验证:
1.不拦截不消费:
即所有的onTouchEvent,onInterceptTouchEvent函数返回为fasle。预期的流程应该是:
当我们点击L2即红色区域程序运行的结果是:
可以看到和我们预期的一模一样。
2.不拦截消费:
这里假定L1对事件不拦截消费,即L1.onInterceptTouchEvent位false,L1.onTouchEvent返回为true,说明L1对消费了事件,且没有拦截事件。同样我们的预期流程应该有两种情况:
第一种:L2消费掉事件,即L2.onTouchEvent返回为true,其流程应该是:
当我们点击L2即红色区域程序运行的结果是:
第二种:L2没有消费掉事件,即L2.onTouchEvent返回为fasle,其流程应该是:
当我们点击L2即红色区域程序运行的结果是:
到这里前两种情况基本介绍完了,总结下,在这里最重要的一点要记住,如果子VIEW没有消费掉ACTION_DOWN的事件,则后续的UP/MOVE事件将不会到来。
3.拦截不消费:
这里假定的对象还是L1,即L1对事件拦截但不消费,即L1.onInterceptTouchEvent位true,L1.onTouchEvent返回为false。从字面上可以L1拦截了事件,则L2是不会在接受到任何事件的。预期的流程应该是:
当我们点击L2即红色区域程序运行的结果是:
可以看到和我们流程图是一样的。
4.拦截消费:
这里假定的对还是L1,即L1对事件拦截且消费,即L1.onInterceptTouchEvent位true,L1.onTouchEvent返回为true。预期的流程应该是:
当我们点击L2即红色区域程序运行的结果是:
运行结果和流程图一样
第三部分:总结
以上就是就是view事件传递的流程,当然还没有包括点击,长按等事件。下面对全文做个总结:
(1) 事件从 Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的 View(ViewGroup)开始一直往下(子 View)传递。子 View 可以通过 onTouchEvent()对事件进行处理。
(2) 事件由父 View(ViewGroup)传递给子 View,ViewGroup 可以通过 onInterceptTouchEvent()对事件做拦截,停止其往下传递。
(3) 如果事件从上往下传递过程中一直没有被停止,且最底层子 View 没有消费事件,事件会反向往上传递,这时父 View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到 Activity 的 onTouchEvent()函数。
(4) 如果 View 没有对 ACTION_DOWN 进行消费,之后的其他事件不会传递过来。
(5) OnTouchListener 优先于 onTouchEvent()对事件进行消费。
源代码:链接:http://pan.baidu.com/s/1sjsUmsP 密码:v6lp
- View事件传递 touch事件分发
- View Touch 事件分发
- View的touch事件分发。
- Android Touch事件分发和传递机制
- android touch事件传递与分发
- android View System touch 事件分发流程
- View的Touch事件分发流程
- Android View Touch的事件分发机制
- View的Touch事件分发机
- View的Touch事件分发简要流程
- View的touch事件分发过程
- Android View touch事件传递方式规律
- Android View Touch事件传递机制
- View 事件传递,分发与拦截
- touch事件分发
- touch事件分发
- Android Touch分发事件
- Touch事件分发
- lucence分词器
- JSON解析:NSData转数组,通过字典转模型的具体实现
- ios coredata的用法和利弊
- 最短路默写
- Javascript Ajax技术运用
- View事件传递 touch事件分发
- iOS中几种数据持久化方案:我要永远地记住你!
- pom.xml中的通用合并策略
- poj 3259 Wormholes(Bellman-Ford)
- iOS学习之 plist文件的读写
- pom.xml中配置plugin
- 获取网络连接名称“本地连接”的两种方法
- [LeetCode]4Sum
- 47. Permutations II