当前位置:网站首页>根据热门面试题分析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扫描工具
- Information Security Experiment 2: using x-scanner scanning tool
- esp8266使用TF卡并读写数据(基于arduino)
- Dynamics 365Online ApplicationUser创建方式变更
- Loxodonframework quick start
- Jmeters use
- Network request process
- How to become a senior digital IC Design Engineer (1-6) Verilog coding Grammar: Classic Digital IC Design
- Netease Cloud Wechat applet
- What development models did you know during the interview? Just read this one
猜你喜欢

stm32和电机开发(从单机版到网络化)

Pytest installation (command line installation)

Pycharm create a new file and add author information

Octopus future star won a reward of 250000 US dollars | Octopus accelerator 2022 summer entrepreneurship camp came to a successful conclusion

csdn涨薪技术-浅学Jmeter的几个常用的逻辑控制器使用

Kubernetes cluster capacity expansion to add node nodes

Information Security Experiment 4: implementation of IP packet monitoring program

Lesson 1: finding the minimum of a matrix
![[bw16 application] Anxin can realize mqtt communication with bw16 module / development board at instruction](/img/7f/d0917366c68865222154d82b9e7b40.png)
[bw16 application] Anxin can realize mqtt communication with bw16 module / development board at instruction

信息安全实验一:DES加密算法的实现
随机推荐
Upload taro pictures to Base64
答案在哪里?action config/Interceptor/class/servlet
进程间的通信方式
Communication mode between processes
thinkphp数据库的增删改查
Loxodonframework quick start
MongoDB怎么实现创建删除数据库、创建删除表、数据增删改查
How to become a senior digital IC Design Engineer (5-3) theory: ULP low power design technology (Part 2)
liunx命令
[4g/5g/6g topic foundation-146]: Interpretation of white paper on 6G overall vision and potential key technologies-1-overall vision
如何成为一名高级数字 IC 设计工程师(5-2)理论篇:ULP 低功耗设计技术精讲(上)
stm32和电机开发(从单机版到网络化)
**grafana安装**
**Grafana installation**
章鱼未来之星获得25万美金奖励|章鱼加速器2022夏季创业营圆满落幕
NETCORE 3.1 solves cross domain problems
如何成为一名高级数字 IC 设计工程师(1-6)Verilog 编码语法篇:经典数字 IC 设计
The use of recycling ideas
Jemter operation
Postman data driven