Android 触摸事件分离原理

news2025/1/20 5:06:54

什么是触摸事件分离?
屏幕上存在多个窗口时,多指触摸的情况下,多个手指的触摸事件可以分给不同的窗口,以下面的图为例,第一个手指按下,window1可以响应这个事件,第二个手指按下(第一个手指不松开),window2同样也可以响应第二个手指按下的事件,两个手指的触摸事件被分离到了不同的窗口,这就是触摸事件分离。
在这里插入图片描述
可以通过配置FLAG_SPLIT_TOUCH(0x00800000)这个flag来设置window是否支持事件分离。默认情况下,系统中的窗口都是支持分离的,所以默认情况下,上图的场景,window1和window2都可以收到触摸事件。

当然我们可以禁用window的事件分离功能,如在主配置文件中配置:

android:windowEnableSplitTouch="false"

只要window1和window2中的任意一个不支持触摸分离,触摸事件只会分发给第一个手指按下的window,第二个手指按下的window将不会接收到触摸事件。

事件分离的原理

这部分逻辑在InputDispatcher 的 findTouchedWindowTargetsLocked方法中,该方法用于查找目标窗口

int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
                                                        const MotionEntry& entry,
                                                        std::vector<InputTarget>& inputTargets,
                                                        nsecs_t* nextWakeupTime,
                                                        bool* outConflictingPointerActions) {
	//省略
	TouchState tempTouchState;
    std::unordered_map<int32_t, TouchState>::iterator oldStateIt =
            mTouchStatesByDisplay.find(displayId);
    if (oldStateIt != mTouchStatesByDisplay.end()) {
        oldState = &(oldStateIt->second);
        tempTouchState.copyFrom(*oldState);//将上次的信息拷贝到tempTouchState中
    }

	bool isSplit = tempTouchState.split;

	bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
                       maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction);//判断是否第一个手指按下

	if (newGesture) {//可以看出,第一个手指按下时,会清空tempTouchState,并将isSplit设为false
        bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
        //省略
        tempTouchState.reset();
        tempTouchState.down = down;
        tempTouchState.deviceId = entry.deviceId;
        tempTouchState.source = entry.source;
        tempTouchState.displayId = displayId;
        isSplit = false;
    }

	//省略
	if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {//1

		sp<InputWindowHandle> newTouchedWindowHandle =
                findTouchedWindowAtLocked(displayId, x, y, &tempTouchState,
                                          isDown /*addOutsideTargets*/, true /*addPortalWindows*/);//查找窗口
                                          
         // Figure out whether splitting will be allowed for this window.
        if (newTouchedWindowHandle != nullptr &&
            newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {//2,支持分离的话将isSplit 设为true
            // New window supports splitting, but we should never split mouse events.
            isSplit = !isFromMouse;
        } else if (isSplit) {// 3
            // New window does not support splitting but we have already split events.
            // Ignore the new window.
            newTouchedWindowHandle = nullptr;
        }

		// Handle the case where we did not find a window.
        if (newTouchedWindowHandle == nullptr) {
            // Try to assign the pointer to the first foreground window we find, if there is one.
            newTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle();//4
        }
		
		if (newTouchedWindowHandle != nullptr) {
			//省略
			 tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);//添加进目标窗口
		}
	}else{
		//省略
		//第二根手指按下并且按下的是不支持事件分离的window时,走这个逻辑
	}
	//省略
}

还是以上图为例,用情景分析的方式,分析下上面的代码逻辑

1,window1和window2都支持分离事件
第一个手指按下的时候,newGesture 为ture,先清空tempTouchState,然后进入注释1的分支,查找到window1窗口后,因为window1窗口支持事件分离,则进入注释2处分支,将isSplit 设为true。然后就是window1加入到tempTouchState中,该事件可分发至window1窗口
第二个手指按下的时候,先将上次的信息拷贝到tempTouchState中(上次将isSplit 设置为true了),所以此次isSplit 也为true,因为不是第一根手指按下newGesture 为false,所以不会清空tempTouchState,但因为是第二根手指按下且isSplit 为true,所以也会进入注释1的分支。查找到window2窗口后,因为window2也支持分离事件,所以也是进入注释2处的分支将isSplit 设为true,然后就是window2加入到tempTouchState中,该事件可分发至window2窗口
所以window1和window2都支持分离事件的话,两个窗口都可以响应对应的触摸事件

2,先按下的window1支持分离事件,window2不支持
第一个手指按下的时候,newGesture 为ture,先清空tempTouchState,然后进入注释1的分支,查找到window1窗口后,因为window1窗口支持事件分离,则进入注释2处分支,将isSplit 设为true。然后就是window1加入到tempTouchState中,该事件可分发至window1窗口
第二个手指按下的时候,先将上次的信息拷贝到tempTouchState中(上次将isSplit 设置为true了),所以此次isSplit 也为true,因为不是第一根手指按下newGesture 为false,所以不会清空tempTouchState,但因为是第二根手指按下且isSplit 为true,所以也会进入注释1的分支。查找到window2窗口后,因为window2不支持分离事件且isSplit 为true,所以这次是进入注释3处的分支又将newTouchedWindowHandle 设为null,所以window2并不会加入到tempTouchState中,该事件就不会分发至window2窗口
所以这种情况下,仅有window1能响应触摸事件,而window2不会响应第二根手指的触摸事件

3,先按下的window1不支持分离事件,window2支持
第一个手指按下的时候,newGesture 为ture,先清空tempTouchState,然后进入注释1的分支,查找到window1窗口后,因为window1窗口不支持事件分离,所以不会设置isSplit 的值,isSplit 还是为false。然后把window1加入到tempTouchState中,该事件可分发至window1窗口
第二个手指按下的时候,先将上次的信息拷贝到tempTouchState中,此次isSplit 还是为false,所以注释1的分支根本就不会进入。注释1处都不会进入的话,就不会去查找窗口,即不会找到window2,该事件就不会分发至window2窗口
所以这种情况下,也是仅有window1能响应触摸事件,而window2不会响应第二根手指的触摸事件

总结
分离事件的逻辑在findTouchedWindowTargetsLocked查找窗口的方法内。如果两个窗口中有一个不支持分离事件,那么只有先按下的那个窗口可以响应触摸事件,另一个窗口并不会响应后面手指的触摸事件。比如在分屏的场景下,如果我们想要在操作我们应用的时候,另一个应用不响应事件,就可以将我们的应用配置成不支持分离事件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1681982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue的学习 —— <vue组件>

目录 前言 正文 一、选项式API与组合式API 二、生命周期函数 1、onBeforeMount() 2、onMounted() 3、onBeforeUpdate() 4、onUpdated() 5、onBeforeUnmount() 6、onUnmounted() 三、组件之间的样式冲突 四、父组件向子组件传递数据 1、定义props 2、静态绑定props…

Elasticsearch 在滴滴的应用与实践

滴滴 Elasticsearch 简介 简介 Elasticsearch 是一个基于 Lucene 构建的开源、分布式、RESTful 接口的全文搜索引擎&#xff0c;其每个字段均可被索引&#xff0c;且能够横向扩展至数以百计的服务器存储以及处理 TB 级的数据&#xff0c;其可以在极短的时间内存储、搜索和分析大…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《集装箱海港级联物流-能源耦合系统协同优化方法 》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

jenkins配置不同版本nodeJS,保姆级叫你配置

问题描述&#xff1a;公司jenkins被改了nodejs版本适配其他项目导致以前的项目构建失败&#xff0c;原因就是nodejs版本太高或太低导致&#xff0c;这里教大家不去更改服务器默认版本&#xff0c;当需要特殊版本直接在jenkins里配置即可。 过程 1、安装nodeJS插件 1.1点击管…

XML文件转TXT文件 yolo标签转换(代码可直接使用) 可批量转换

像这样的xml文件&#xff0c;我们可以通过代码批量转换为txt文件格式&#xff1a; 新建一个xml2txt.py文件&#xff0c; 上代码&#xff0c;直接复制粘贴 import xml.etree.ElementTree as ET import osdef convert(size, box):x_center (box[0] box[1]) / 2.0y_center (box…

2020 年第一届辽宁省大学生程序设计竞赛

比赛经历&#xff1a;摸鱼划水了一个多小时又是只会签到&#xff0c;看来还得提升自己的解题能力写了六题 补题&#xff1a;E线段树维和区间平方和&#xff0c;比较经典好久没写过线段树了傻了&#xff0c;注意维护lazy J计算几何&#xff0c;看来得提上日程了&#xff0c;用叉…

0.98T优于10米高程DEM数据

我们在《全球30米100%水陆覆盖高程》一文中&#xff0c;为大家分享了全球100%覆盖&#xff0c;且包括海底高程的30米DEM数据。 该数据虽然全球无死角覆盖&#xff0c;但分辨率只有30米。 这里&#xff0c;再为大家分享一个优于10米的高程数据&#xff0c;但目前仅覆盖全国范围…

The 13th Shandong ICPC Provincial Collegiate Programming Contest

The 13th Shandong ICPC Provincial Collegiate Programming Contest The 13th Shandong ICPC Provincial Collegiate Programming Contest A. Orders 题意&#xff1a;有n个订单&#xff0c; 每日可生产k个产品&#xff0c;每个订单给出交付日和交付数量&#xff0c;是否能…

每日一练 2024.5.16(补 2024.5.14)

题目&#xff1b; 我们定义 arr 是 山形数组 当且仅当它满足&#xff1a; arr.length > 3存在某个下标 i &#xff08;从 0 开始&#xff09; 满足 0 < i < arr.length - 1 且&#xff1a; arr[0] < arr[1] < ... < arr[i - 1] < arr[i]arr[i] > arr…

泛微E9开发 自动获取日期

选择开始日期&#xff0c;自动获取指定天数后的结束日期 1、功能背景2、展示效果3、实现方法 1、功能背景 用户选择开始日期&#xff0c;系统自动带出结束日期&#xff0c;如需要带出6天后的结束日期&#xff0c;下图所示&#xff0c;5月14日到5月20日是一个周期&#xff0c;用…

Linux-centos下安装ffmpeg的详细教程

源安装 第一种方式&#xff1a; . 首先需要安装yum源&#xff1a; 这个源安装的ffmpeg版本是3.4 yum install epel-release yum install -y https://mirrors.ustc.edu.cn/rpmfusion/free/el/rpmfusion-free-release-7.noarch.rpm然后可以安装ffmpeg yum install -y ffmpeg ff…

电阻式传感器

电阻式传感器是一种将非电学量&#xff08;如温度、压力、位移等&#xff09;转换为电阻变化的传感器。它大致分为电阻应变式传感器、压阻式传感器和变阻式传感器三类。 电阻式传感器的优点包括结构简单、成本低廉、稳定性好&#xff0c;适用于多种环境。但它们也有局限性&…

第十四届蓝桥杯大赛软件赛国赛C/C++ 大学 B 组 AB路线

//bfs 1000100010不会超时 #include<bits/stdc.h> using namespace std; #define int long long const int n1e311; int a,b,c,h[n][n][12],k[4][2]{0,1,0,-1,1,0,-1,0}; char t[n][n]; struct s {int x,y,z,w; }; signed main() {ios::sync_with_stdio(false);cin.t…

VMware虚拟机-安装程序无法自动安装virtual machine......_windows server 2008 R2

系统版本&#xff1a;windows server 2008 R2 问题-安装程序无法自动安装virtual machine… 在使用虚拟机安装windows server 2008 R2系统中&#xff0c;安装VMware Tools工具安祖啊寄给你失败&#xff0c;提示安装程序无法自动安装virtual machine…&#xff0c;必须手动安装…

lazada、shopee新店铺如何快速出单?自养号补单测评实战操作指南

作为一家Lazada、虾皮新店铺&#xff0c;要快速出单&#xff0c;需要采取一些策略和措施。以下是一些可以考虑的方法&#xff1a; 一、优化产品信息 确保您的产品信息完整、准确、清晰&#xff0c;并且可以吸引潜在客户。这包括商品标题、描述、图片、价格等。 二、优化店铺…

其他自动化工程师都在偷偷学习AI技术,你再不学就落后了!一篇文章教会你使用AI!

其他自动化工程师都在偷偷学习AI技术&#xff0c;你再不学就落后了&#xff01;一篇文章教会你使用AI&#xff01; 哈喽&#xff0c;大家好&#xff0c;我是小叔。了解小叔的朋友都清楚&#xff0c;我从来都不是标题党&#xff0c;我只会用美女图片来吸引你们&#x1f602;&am…

如何管理研发人员

在日益激烈的市场竞争中&#xff0c;企业的核心竞争力往往取决于其技术创新能力和研发实力。然而&#xff0c;随着企业研发的深入和技术的积累&#xff0c;研发人员泄密的风险也愈发严重。如何防止研发人员泄密&#xff0c;已经成为企业面临的重要问题。本文将从加强员工保密意…

前端简史之崛起:Router迁鼎

引 &#x1f4a1; Ajax 的出现&#xff0c;带来了 jQuery 时代&#xff1b;Node技术的发展&#xff0c;带来了前端工程化进阶&#xff1b;如果说前面二者是带来技术的革命&#xff0c;那么前端路由方案的多样化则带来了用户体验的升级以及项目管理的优化。 课程简介 《前端简史…

AI for Good | 我们用“AI”保护地球

4月&#xff0c;草长莺飞的春夏之交&#xff0c;我们将迎来第55个世界地球日 (The World Earth Day)。在这个不断变暖的星球上&#xff0c;我们面临着一个巨大的挑战&#xff1a;气候变化。随着极端天气事件的频发&#xff0c;如何汇聚社会各界的共同努力&#xff0c;找到创新的…

【网站项目】SpringBoot379儿童疫苗接种管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…