当前位置:网站首页>根据热门面试题分析Android事件分发机制(二)---事件冲突分析处理
根据热门面试题分析Android事件分发机制(二)---事件冲突分析处理
2022-07-07 07:03:00 【光阴剑客】
(一)事件冲突概述
事件冲突一般发生在父view和子view的组合中,比如说viewpager和listview 的组合中。产生事件冲突的原因是一个事件(down,up,move)到来时,有时候我们希望是A view处理,但是却是B view处理。这样就导致了我们想处理事件的view收不到事件,不想处理事件的view收到了事件。而解决冲突就是我们通过viewGroup的onInterceptTouchEvent()方法去合理的分发事件,让想处理事件的view收到事件,不想处理的view躺平啥也不做。
(二)没有事件冲突的效果展示
(看看美女,再写代码~~)
言归正传,如上图所示,demo是由一个viewpager+listView的组合,我们发现在没有事件冲突的情况下,应该是既能左右滑动,也能上下滑动。为了演示,我们分别继承自viewpager和Listview,viewPager作为父view,重写它的onInterceptTouchEvent方法,listview作为子view,重写dispatchTouchevent.(需要的时候),demo的源码很简单,我会在文章末尾给出。
(说明:如果不重写onInterceptTouchEvent和listview的dispatchTouchevent方法,我们直接使用viewpager+listview组合会发现不会产生事件冲突,那是因为sdk里面已经解决了冲突,可以查看viewpager的源码)
模拟冲突的产生 :
情景1: 当我们在父view,也就是viewPager的onInterceptTouchEvent方法中直接返回true,拦截事件,这时候我们会发现我们只可以响应view pager的左右滑动,而不能响应listview的上下滑动,原因就是我们在父view直接拦截了事件,导致子view listview 收不到事件,无法响应事件。
情景2: 当我们在父view,也就是viewPager的onInterceptTouchEvent方法中直接返回false,不拦截事件,我们这时会发现,viewpager 不可以左右滑动,只可以上下滑动listview,这是因为viewpager不拦截事件,将事件分发给了子view处理,所以他无法响应自己的左右滑动事件。
(三)面试题:你遇到过滑动冲突吗?你是怎么处理的?
解析: 这时假如你自己遇到过,就答你遇到的冲突产生的情景,然后说下你的解决方法,如果你没有遇到过,就回答咱们本文中提到的viewpager+listview的场景。根据上面的内容总结下就可以,然后就是如何解决冲突的回答,这时候你可以回答有两种冲突解决方法:
方法一:在父view的onInterceptTouchEvent中解决冲突,代码如下:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//在父view中进行冲突处理,不需要子view实现dispatchTouchEvent方法
float x = ev.getX();//记录下x,y的初始值
float y = ev.getY();
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
super.onInterceptTouchEvent(ev);
//这里需要调用sdk中的viewpager中的
//onInterceptTouchEvent方法处理一些特殊问题
//不调用的话我们拦截了事件也无法响应滑动
return false;//不能拦截down事件,拦截了down
//事件,就无法收到后面的move,和up事件了
case MotionEvent.ACTION_MOVE:
float xDiff = Math.abs(x-mLastX);
//当move事件来的时候我们去计算本次的x值和上次的
//x值,得到一个差值
float yDiff = Math.abs(y-mLastY);
//y值的计算和x一样
if(xDiff > yDiff){
//x的差值大于y的差值,表示当前是左右滑动。此时应该把事件交给viewpager处理,拦截事件
isIntercept = true;
break;
}
if(yDiff > xDiff){
//y值大于x值,表示当前是上下滑动,此时应该把事件交给listview处理,不拦截事件
isIntercept = false;
break;
}
// break;
}
mLastX = x;//更新上一次的x值和y值
mLastY = y;
return isIntercept;
}
方法2:在子view中做滑动冲突处理,listview中的代码如下:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
float x = ev.getX();
float y = ev.getY();
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);
//请求父view不拦截事件
break;
case MotionEvent.ACTION_MOVE:
float xDiff = Math.abs(x-mLastX);
float yDiff = Math.abs(y-mLastY);
if(xDiff > yDiff){
//当前是左右滑动,自己不需要处理事件,请求父view拦截事件。
getParent().requestDisallowInterceptTouchEvent(false);
}
break;
default:break;
}
mLastX = x;
mLastY = y;
//调用父类的dispatchTouchEvent处理事件
return super.dispatchTouchEvent(ev);
}
viewPager中的代码如下:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//在子view中进行冲突处理.
if(ev.getAction() == MotionEvent.ACTION_DOWN){
super.onInterceptTouchEvent(ev);
//必须返回false,否则子view无法收到事件,此处会有一个面试题
return false;
}
//返回true,是为了当子view请求父view拦截事件的时候,好拦截事件
return true;
}
在子view中处理冲突和在父view中处理冲突的原理差不多,都是通过拦截和不拦截的方式将事件分给需要的view。回答的时候就把两种方法大致描述一下。
然后接着,面试官可能会问你:为啥不能拦截down事件,拦截了down事件,后面的move,up事件还能收到吗?
这两个问题其实互为因果,也就是拦截了down事件,后面的move,up事件都无法收到了。这时候你就可以开始将你看的事件分发机制的源码摆出来了:
...省略了部分代码
// Check for interception.
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
//如果子view没有调用requestDisallowInterceptTouchEvent方法设置标志的话,这个地方会为false,因为在前面down事件来的时候会重置一下标志
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);//若是拦截了down事件,这个地方会返回true;无法进入到接下来的事件分发逻辑,然后mFirstTouchTarget就不会被赋值,无法走入到当前的代码逻辑中,导致后面来的move和up事件直接会被拦截
=============插播片段==============
if (!canceled && !intercepted) {
....
// 事件分发处理逻辑
.....
}
===========================
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
//如果没有处理down事件的时候,move和up事件都会被拦截
intercepted = true;
}
...省略了部分代码
具体的事件分发流程,可以看我上一篇博客根据热门面试题分析Android事件分发机制(一)
(四)总结:
其实事件分发机制和滑动冲突只要理解了源码都不难解决,我的建议就是要看博客然后自己去撸源码,写demo模拟每一种场景,这时你就会发现这些原理都是通的,在面试的时候也能帮你拿到主动权,大多数时候我们面试的时候感觉自己都被面试官气势给压住,其实都是我们技术了解得不深的原因。当我们技术了解得够透彻的时候,你去面试的时候会发现,面试官会被你虐的。那种感觉特别爽
(五)demo地址
这个源码我是放到gitee上的,已经申请了开放权限,还在审批,如果急须源码的伙伴,可以留个邮箱,我私发给你们~~~~
事件冲突演示demo地址
边栏推荐
- 信息安全实验二 :使用X-SCANNER扫描工具
- Kubernetes cluster capacity expansion to add node nodes
- Sublime Text4 download the view in bower and set the shortcut key
- 数据建模中利用3σ剔除异常值进行数据清洗
- JMeter JDBC batch references data as input parameters (the simplest method for the whole website)
- 【BW16 应用篇】安信可BW16模组/开发板AT指令实现MQTT通讯
- 其实特简单,教你轻松实现酷炫的数据可视化大屏
- How to become a senior digital IC Design Engineer (5-2) theory: ULP low power design technology (Part 1)
- (3/8) method parameters of improper use of enumeration (2)
- The configuration and options of save actions are explained in detail, and you won't be confused after reading it
猜你喜欢
Jenkins modifies the system time
JMeter JDBC batch references data as input parameters (the simplest method for the whole website)
【云原生】DevOps(一):DevOps介绍及Code工具使用
Strategic cooperation subquery becomes the secret weapon of Octopus web browser
Information Security Experiment 2: using x-scanner scanning tool
Oracle installation enhancements error
In fact, it's very simple. It teaches you to easily realize the cool data visualization big screen
Unity3d interface is embedded in WPF interface (mouse and keyboard can respond normally)
[SVN] what is SVN? How do you use it?
Network request process
随机推荐
JS reverse tutorial second issue - Ape anthropology first question
Loxodonframework quick start
How will fashion brands enter the meta universe?
答案在哪里?action config/Interceptor/class/servlet
Kubernetes cluster capacity expansion to add node nodes
Variable parameter of variable length function
Mysql database lock learning notes
SAP MM STO单据的外向交货单创建后新加ITEM?
IIS redirection redirection appears eurl axd
Pycharm importing third-party libraries
Unity shader (data type in cghlsl)
Nested (multi-level) childrn routes, query parameters, named routes, replace attribute, props configuration of routes, params parameters of routes
Oracle installation enhancements error
[4G/5G/6G专题基础-146]: 6G总体愿景与潜在关键技术白皮书解读-1-总体愿景
Esp8266 uses TF card and reads and writes data (based on Arduino)
[SVN] what is SVN? How do you use it?
Sublime Text4 download the view in bower and set the shortcut key
MongoDB怎么实现创建删除数据库、创建删除表、数据增删改查
Jenkins+ant+jmeter use
scrapy爬虫mysql,Django等