浅谈Android 事件分发机制(一)
Android事件分发机制是Android开发者必须了解的知识,这方面的内容很多,自己纯看文章总觉得比较抽象,自己写了个demo,理一下事件分发的流程,加深印象。
view结构
PhoneWindow 的指示通过 DecorView 传递给下面的 View,下面 View 的信息也通过 DecorView 回传给 PhoneWindow。这里我们主要聊聊ViewGroup与view的事件分发
类型 | 相关方法 | ViewGroup | View |
---|---|---|---|
事件分发 | dispatchTouchEvent | √ | √ |
事件拦截 | onInterceptTouchEvent | √ | × |
事件消费 | onTouchEvent | √ | √ |
事件分发dispatchTouchEvent
一般改写不多,主要关注另外两个。
事件拦截onInterceptTouchEvent
,true,拦截,交给自己的onTouchEvent处理,不传给下级;false,不拦截,传给下级。
事件消费onTouchEvent
,true,自己搞定消费,不用上传;false,上传。
事件模拟
如图布局,最外层的父布局ViewGroupA,中间层的ViewGroupB,最里层的ViewC
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <com.qhyccd.event.ViewGroupA app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="100dp" android:layout_width="300dp" android:layout_height="300dp" android:background="@color/colorRed"> <com.qhyccd.event.ViewGroupB android:layout_width="200dp" android:layout_height="200dp" android:background="@color/colorYellow"> <com.qhyccd.event.ViewC android:layout_width="100dp" android:layout_height="100dp" android:background="@color/colorBlue" /> </com.qhyccd.event.ViewGroupB> </com.qhyccd.event.ViewGroupA> </FrameLayout>
首先模拟下以上场景,A、B、C三个角色,A>B>C
ViewGroupA
public class ViewGroupA extends LinearLayout { public ViewGroupA(Context context) { super(context); } public ViewGroupA(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public ViewGroupA(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i("》》》", " ViewGroupA dispatchTouchEvent "); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i("》》》", " ViewGroupA onInterceptTouchEvent "); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("》》》", " ViewGroupA onTouchEvent "); return super.onTouchEvent(event); } }
ViewGroupB
public class ViewGroupB extends LinearLayout { public ViewGroupB(Context context) { super(context); } public ViewGroupB(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public ViewGroupB(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i("》》》", " ViewGroupB dispatchTouchEvent "); return super.dispatchTouchEvent(ev);; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i("》》》", " ViewGroupB onInterceptTouchEvent "); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("》》》", " ViewGroupB onTouchEvent "); return super.onTouchEvent(event); } }
ViewC
public class ViewC extends View { public ViewC(Context context) { super(context); } public ViewC(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public ViewC(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i("》》》", " ViewC dispatchTouchEvent "); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("》》》", " ViewC onTouchEvent "); return super.onTouchEvent(event); } }
情景一
默认情况下,点击C区域
ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupB dispatchTouchEvent ViewGroupB onInterceptTouchEvent ViewC dispatchTouchEvent ViewC onTouchEvent ViewGroupB onTouchEvent ViewGroupA onTouchEvent
可见,事件是从A->B->C,再从C->B->A回传
情景二
A想自己把事件拦截,不给下级处理,A里面onInterceptTouchEvent
返回ture拦截事件
ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupA onTouchEvent
情景三
B想自己把事件拦截,不给下级处理,B里面onInterceptTouchEvent
返回ture拦截事件。
ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupB dispatchTouchEvent ViewGroupB onInterceptTouchEvent ViewGroupB onTouchEvent ViewGroupA onTouchEvent
B这里只是对事件拦截不往下传递,还是会往上回传的。
如果想让B自己把事件消费,不往上级传递,B的onTouchEvent
返回true
ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupB dispatchTouchEvent ViewGroupB onInterceptTouchEvent ViewGroupB onTouchEvent
情景四
C属于最底层view,对事件没有拦截权限,C自己想把事件消费了,C的onTouchEvent
返回true
,不再往上级回传
ViewGroupA dispatchTouchEvent ViewGroupA onInterceptTouchEvent ViewGroupB dispatchTouchEvent ViewGroupB onInterceptTouchEvent ViewC dispatchTouchEvent ViewC onTouchEvent
以上是静态点击事件处理流程,模拟的事件分发机制,通过log打印可以看到事件的传递流程,这篇文章属于基础篇章,后续我们给view添加滑动,通过处理滑动冲突进一步理解事件的分发机制,敬请期待下一篇。
END
祝大家五一劳动节快乐!致敬奋斗在一线的码农!
欢迎关注微信号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
2018届android校招面试总结:百度,大疆,乐视,知乎
写在前面 四月面临了人生第一次比较重大的变化:现在的公司因为融资不利,收回了我的正式offer。这一波很伤... 所以在得知消息之后,接下来差不多一个月的时间里,自己开始了的频繁的面试之旅。其中有导师/朋友给内推的,也有自投的.... 感兴趣的看官,可以看看我的其他文章:1、常用集合的源码分析:HashMap2、Java反射实践:从反射中理解class3、从公司项目配置看Gradle 面试记录 首先,我是一个双非本科的大四狗,一直在搞安卓,自学一年多的时间,然后有半年多的实习经历...安卓真好玩,就是肚子有点饿~ 接下来,按时间的顺序的记一记我这一个月以来所经历的面试。 百度:社招(导师内推) 一面: 1、四种启动模式,结合具体情况分析。 2、onNewIntent被回调,Intent内容是最新的么?那其他回调里的Intent是最新的么? 3、Service的start和bind的区别?多次start和bind的生命周期情况?start和bind都调用了会怎么样? 4、常见的内存泄漏/内存溢出?怎么解决? 5、多进程application会初始化几次?怎样进行跨进程通讯?SP属于文件,...
- 下一篇
Debugexperience about SQLite & LitePal:创建数据库闪退?注意小括号
参考资料:《第一行代码》 源码(码云): 今天在做一个SQLite的Demo,在Create一个数据库的时候居然闪退: UI: 还以为是权限问题结果看一下logcat,额。。。 发现了这一句, 其实就是SQL语句少了一个右括号(第18行): 嗯,编写程序的时候,要细心一点。 *****另外, 在添加表/更改onUpgrade()之后,记得在调用的代码那里(下图第16行),更改第四个参数(version): 不然创建数据库的时候: 一个关于LitePal的Error: 注意mapping标签下要写入正确的完整的类名: 下面是错误的示范: 对应会出现的bug: 正确写法: 另外注意: 1.litepal.xml文件要放在assets目录下; 2.文件须命名为“litepal.xml”,如下图。如果命名为“litepal(没有".xml")”,则会同上一般报错: 参考文档:Android Studio 使用litepal 无法创建数据库
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Hadoop3单机部署,实现最简伪集群
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果