Android 分发事件机制
来源:互联网 发布:淘宝商城女休闲鞋 编辑:程序博客网 时间:2024/05/16 09:32
前言
当Android系统捕获到用户的各种输入事件后,如何准确地传递给真正需要这个事件的控件呢?Android给我们提供了一整套完善的事件传递、处理机制,来帮助开发者完成准确的事件分配和处理。
基础知识
- MotionEvent
- 所有触摸事件都被封装成MotionEvent对象,包括Touch的位置、时间、历史记录以及第几个手指(多指触摸)等。
- 一次完整的MotionEvent事件,是从用户触摸屏幕到离开屏幕。整个过程的动作可如示:ACTION_DOWNACTION_DOWN(1次)-> ACTION_MOVE(N次)- > ACTION_UP(1次)
- 多点触摸,每一个触摸点Pointer会有一个id和index。对于多指操作,通过pointerindex来获取指定Pointer的触屏位置。比如,对于单点操作时获取x坐标通过getX(),而多点操作获取x坐标通过getX(pointerindex)
- View
- View是所有视图对象的父类,实现了动画相关的接口Drawable.Callback, 按键相关的接口KeyEvent.Callback, 交互相关的接口AccessibilityEventSource。比如Button继承自View。
- TouchEvent事件处理相关的方法:
dispatchTouchEvent(MotionEvent event)
onTouchEvent(MotionEvent event)
- ViewGroup
- ViewGroup,是一个abstract类,一组View的集合,可以包含View和ViewGroup,是所有布局的父类或间接父类。继承了View,实现了ViewParent(用于与父视图交互的接口), ViewManager(用于添加、删除、更新子视图到Activity的接口)。比如常用的LinearLayout,RelativeLayout都是继承自ViewGroup。
- TouchEvent事件处理相关的方法:
dispatchTouchEvent(MotionEvent event)
onInterceptTouchEvent(MotionEvent ev)
onTouchEvent(MotionEvent event)
- Activity
- Activity是Android四大基本组件之一,这里只介绍Activity与touch相关的方法。当手指触摸到屏幕时,屏幕硬件一行行不断地扫描每个像素点,获取到触摸事件后,从底层产生中断上报。再通过native层调用Java层InputEventReceiver中的dispatchInputEvent方法。经过层层调用,交由Activity的dispatchTouchEvent方法来处理。
- TouchEvent事件处理相关的方法:
dispatchTouchEvent(MotionEvent event)
onTouchEvent(MotionEvent event)
流程图
当用户触摸屏幕时会产生一系列MotionEvent,那么Activity,ViewGroup,View之间是如何处理呢?这里通过一张图来从全局性描述整个流程
结论
流程图总结
onInterceptTouchEvent返回值true表示事件拦截, onTouch/onTouchEvent 返回值true表示事件消费。
触摸事件先交由Activity.dispatchTouchEvent。再一层层往下分发,当中间的ViewGroup都不拦截时,进入最底层的View后,开始由最底层的OnTouchEvent来处理,如果一直不消费,则最后返回到Activity.OnTouchEvent。
ViewGroup才有onInterceptTouchEvent拦截方法。在分发过程中,中间任何一层ViewGroup都可以直接拦截,则不再往下分发,而是交由发生拦截操作的ViewGroup的OnTouchEvent来处理。
子View可调用requestDisallowInterceptTouchEvent方法,来设置disallowIntercept=true,从而阻止父ViewGroup的onInterceptTouchEvent拦截操作。
OnTouchEvent由下往上冒泡时,当中间任何一层的OnTouchEvent消费该事件,则不再往上传递,表示事件已处理。
如果View没有消费ACTION_DOWN事件,则之后的ACTION_MOVE等事件都不会再接收。
只要View.onTouchEvent是可点击或可长按,则消费该事件.
onTouch优先于onTouchEvent执行,上面流程图中省略,onTouch的位置在onTouchEvent前面。当onTouch返回true,则不执行onTouchEvent,否则会执行onTouchEvent。onTouch只有View设置了OnTouchListener,且是enable的才执行该方法。
区分总结
View触摸事件传递机制:
- 触摸控件(View)首先执行dispatchTouchEvent方法。
- 在dispatchTouchEvent方法中先执行onTouch方法,后执行onClick方法
- 如果控件(View)的onTouch返回false或者mOnTouchListener为null(控件没有设置setOnTouchListener方法)或者控件不是enable的情况下会调运onTouchEvent,dispatchTouchEvent返回值与onTouchEvent返回一样。
- 如果控件不是enable的设置了onTouch方法也不会执行,只能通过重写控件的onTouchEvent方法处理(上面已经处理分析了),dispatchTouchEvent返回值与onTouchEvent返回一样。
- 如果控件(View)是enable且onTouch返回true情况下,dispatchTouchEvent直接返回true,不会调用onTouchEvent方法。
- 当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发下一个action(也就是说dispatchTouchEvent返回true才会进行下一次action派发)。
ViewGroup触摸事件传递机制:
- Android事件派发是先传递到最顶级的ViewGroup,再由ViewGroup递归传递到View的。
- 在ViewGroup中可以通过onInterceptTouchEvent方法对事件传递进行拦截,onInterceptTouchEvent方法返回true代表不允许事件继续向子View传递,返回false代表不对事件进行拦截,默认返回false。
- 子View中如果将传递的事件消费掉,ViewGroup中将无法接收到任何事件。
Activity触摸事件传递机制:
- 首先会触发Activity的dispatchTouchEvent方法
- dispatchTouchEvent方法中如果是ACTION_DOWN的情况下会接着触发onUserInteraction方法。
- 接着在dispatchTouchEvent方法中会通过Activity的root View(id为content的FrameLayout),实质是ViewGroup,通过super.dispatchTouchEvent把touchevent派发给各个activity的子view,也就是我们再Activity.onCreat方法setContentView时设置的view。
- 若Activity下面的子view拦截了touchevent事件(返回true)则Activity.onTouchEvent方法就不会执行
最后
附上我的测试源码地址:https://github.com/myloften/ViewEventSample/tree/master
如需查看更详细的源码分析,请看以下博客分析:
Android触摸屏事件派发机制详解与源码分析一(View篇)
Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇)
Android触摸屏事件派发机制详解与源码分析三(Activity篇)
Android事件分发机制
- android事件分发机制
- Android事件分发机制
- Android 事件分发机制
- Android事件分发机制
- Android 事件分发机制
- Android 事件分发机制
- android 事件分发机制
- Android事件分发机制
- android 事件分发机制
- android事件分发机制
- Android 事件分发机制
- android事件分发机制
- android 事件分发机制
- android 事件分发机制
- Android 事件分发机制
- Android事件分发机制
- Android事件分发机制
- Android 事件分发机制
- 跟着SY速学Ubuntu系列二:Ubuntu16 编译安装 Apache24&&PHP7&&Mysql57
- swift基本语法(总结提炼版)之014 swift 之闭包循环引用
- SGX——多年的技术2016年终于有了SDK下载
- 【转】mysql语句大全
- Nginx值location匹配规则
- Android 分发事件机制
- Android 入门项目NoteBook
- Linux基础----文件目录
- OptiStruct] Altair OptiStruct之前世今生
- day5.23总结_Socket(单聊和群聊)
- servlet、filter、listener、interceptor区别
- 关于kaggle如何下手
- 第七届 科技节 电子设计大赛 三等奖作品---基于STC89C51单片机的温控风扇
- 上海复旦大学吴立德教授深度学习课程一