安卓窗口window无法移除屏幕外超过屏幕边界?-wms源码层面深入剖析

Android WMS深度解析:从窗口管理到车机系统实战 在Android系统开发中,窗口管理是构建复杂用户界面的核心技术基础。其核心原理在于通过WindowManagerService(WMS)统一管理系统中的所有窗口(Window),负责窗口的创建、排序(Z-order)、布局以及输入事件分发。这项技术的核心价值在于为应用提供了稳定、高效的显示与交互基础,尤其在多窗口、分屏以及系统级悬浮窗等高级场景中不可或缺。在智能座舱、车机系统等复杂应用场景下,对WMS的深入理解和定制能力直接决定了系统UI的稳定性与表现力。本文聚焦WMS的架构设计与实战,通过剖析窗口类型、 阅读详情

背景

学习了上一节的窗口位置变化相关的内容后,在窗口移动过程过程中发现有一个限制问题,大家可以看一下如下动态图:
在这里插入图片描述

已经尽力把窗口想要拖到屏幕外面,但是一直拖到不生效,只能在屏幕内部进行移动,这个到其实很奇怪,因为对于LayoutParam的x,y坐标是有进行设置的,为啥设置了就不生效呢?

这里看看是不是应用层面还是哪里限制了,可以通过wms的Relayout的Attribute属性看看,明显看到有负数坐标,即app层面已经把移除屏幕的x坐标传递到了wms,但是最后wms并没有让这个传递来的坐标生效。
在这里插入图片描述

分析为啥不可以超出屏幕边界

这里要分析就一样也要日志中开始分析
frameworks/base/core/java/android/view/WindowLayout.java
在这里插入图片描述
前面分析位置变化就这里Gravity.apply坐标就有了变化,这里我们看看日志:
在这里插入图片描述
可以看到这里的Gravity.apply执行完成后确实x方向坐标是负的,但是继续往下看看computeFrames自带的日志:
在这里插入图片描述
却得到如下结果:
在这里插入图片描述
可以看到x的坐标其实从-93变成了0,这里最后的打印也就是实际显示的,那么到底是哪里吧-93变成0呢?

在这里插入图片描述
这里再查阅代码发现有个二fitToDisplay,即这里看着有个适配屏幕操作,也会改变这个坐标,这里也加入一下打印
在这里插入图片描述

从日志也可以看出来:
在这里插入图片描述

剖析一下fitToDisplay

  final boolean fitToDisplay = !inMultiWindowMode
            || ((attrs.type != TYPE_BASE_APPLICATION) && !noLimits);

注意可以看到这里有多个限制,如果想让fitToDisplay不为true,其实还是有较多方法,这里可以考虑noLimits

        final boolean noLimits = (attrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;

再看看applyDisplay方法

    public static void applyDisplay(int gravity, @NonNull Rect display, @NonNull Rect inoutObj) {
        if ((gravity&DISPLAY_CLIP_VERTICAL) != 0) {
            if (inoutObj.top < display.top) inoutObj.top = display.top;
            if (inoutObj.bottom > display.bottom) inoutObj.bottom = display.bottom;
        } else {
            int off = 0;
            if (inoutObj.top < display.top) off = display.top-inoutObj.top;
            else if (inoutObj.bottom > display.bottom) off = display.bottom-inoutObj.bottom;
            if (off != 0) {
                if (inoutObj.height() > (display.bottom-display.top)) {
                    inoutObj.top = display.top;
                    inoutObj.bottom = display.bottom;
                } else {
                    inoutObj.top += off;
                    inoutObj.bottom += off;
                }
            }
        }
        
        if ((gravity&DISPLAY_CLIP_HORIZONTAL) != 0) {
            if (inoutObj.left < display.left) inoutObj.left = display.left;
            if (inoutObj.right > display.right) inoutObj.right = display.right;
        } else {
            int off = 0;
            if (inoutObj.left < display.left) off = display.left-inoutObj.left;
            else if (inoutObj.right > display.right) off = display.right-inoutObj.right;
            if (off != 0) {
                if (inoutObj.width() > (display.right-display.left)) {
                    inoutObj.left = display.left;
                    inoutObj.right = display.right;
                } else {
                    inoutObj.left += off;
                    inoutObj.right += off;
                }
            }
        }
    }

明显可以看出这里会对设置的frame的left和display的left,这样就把我们最后窗口显示限制在display以内。

那么问题就清楚了,其实本质就是因为computeFrames的里面有个applyDisplay方法会判断是否超出屏幕,从而让window限制显示在屏幕里面。

解决超出屏幕限制方法:

上面分析fitToDisplay有提到这个标志就是限制根本


  final boolean noLimits = (attrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
  final boolean fitToDisplay = !inMultiWindowMode
            || ((attrs.type != TYPE_BASE_APPLICATION) && !noLimits);

但是这个标志实际上app层面是可以控制的,考虑把这里的noLimits对应的FLAG_LAYOUT_NO_LIMITS带上,尝试看看
在这里插入图片描述
再运行测试如下:
在这里插入图片描述

完美运行,可以正常超出屏幕边界。

更多framework技术干货,请关注下面“千里马学框架”

Android开机屏幕旋转导致触摸错乱:系统级排查与修复指南 在Android系统开发中,屏幕方向管理与触摸坐标映射是基础且关键的技术点。其核心原理在于显示子系统与输入子系统间的协同:显示服务(如WindowManager)确定屏幕方向后,输入服务(如InputReader)需据此对触摸驱动上报的原始坐标进行旋转变换,以匹配显示内容。若两者在初始化时序或配置上不同步,就会导致严重的触摸错乱问题,直接影响用户体验。这类问题在搭载旋转传感器的设备(如平板、车机)上尤为常见,常表现为开机后屏幕被意外旋转,继而引发触摸坐标映射错误。从工程实践角度,开发者需系统性排查BootA 阅读详情

相关推荐

第 23 章:窗口系统

Insets 代表屏幕被系统 UI(状态栏、导航栏、IME)或硬件特性(挖孔、圆角)占用的区域。窗口布局时需要避开这些区域。Insets 系统从旧演进到现代与。

dengfuma的专栏 369

Android T WMS窗口相关流程

什么是窗口 窗口即是屏幕上的一块用于绘制各种UI元素并可以响应用户输入的一个矩形区域。从原理上讲,窗口的概念是独自占有一个Surface实例的显示区域(我们在屏幕上看到的图形都需要绘制在Surface上)。 Window是个抽象类其实现类为PhoneWindow。

yimelancholy的博客 1万+

Android窗口管理系统深度剖析:从创建到销毁的完整旅程

本文深入解析Android窗口管理服务(WMS)的核心机制,从源码层面剖析窗口生命周期全流程管理。重点内容包括:WindowToken体系实现窗口层级绑定、WindowState结构管理窗口实例、跨进程协作的窗口创建流程、动态Z-Order计算引擎、窗口状态迁移控制逻辑、输入法窗口特殊处理、屏幕旋转重建机制、熄屏亮屏状态转换以及资源防泄露设计。通过5000行源码分析揭示了WMS如何协调系统窗口、应用窗口和输入法窗口的显示与交互,并提供了典型面试问题的技术解答。

郑伟强dev的专栏 63

android 13 WMS/AMS系统开发-WindowManagerService相关relayout操作

主要就有2个最关键步骤:1、创建对应Window的SurfaceControl2、计算出对应的window区域等,把inset和config传递回去更多内容qqun:422901085。

liaosongmao1的专栏 576

中山大学_数据科学与计算机_预推免

前言 2019 年 9 月中旬是中山大学预推免时间,本人没能进到夏令营,但是最后在预推免上岸也算不幸中的万幸。 记忆不一定准确,但希望能帮到他人。 想看 流程 的可以直接看总结,正文部分有本人心路历程。 预推免 中山大学的预推免大致可以分为 报道,机试,面试 三大部分,而且尤其是面试,所有人加起来总时长 3 天,幸运的是,本人被安排在第一天的下午第一场,上午就是机试,报道,机试,面试,无缝衔接。 ...

一把健 5210

Dify社区版多工作空间功能解锁:源码修改与多租户架构解析

多租户架构是现代SaaS平台实现数据隔离与资源管理的核心技术,其核心原理是通过租户模型将用户、应用和数据在逻辑上隔离。在AI应用开发平台中,这种架构能有效支持多团队、多项目并行开发,确保不同业务线的数据安全与独立迭代。Dify作为开源AI应用构建平台,其底层已设计完善的多租户模型,但社区版默认限制了单用户单工作空间。本文通过精准修改两处关键代码——账户初始化逻辑与系统功能开关,释放了平台固有的多工作空间管理能力。该方案无需改动数据库结构,直接利用现有RBAC权限体系,实现了类似企业版的**多租户隔离**体验

weixin_27059669的博客 1065

Android Framework(五)WMS-窗口显示流程——窗口布局与计算

1、WindowState 本身对应的是“容器”类型的 Surface ,在“addWindow流程”就创建了,而 relayoutWindow 创建的是一个“BufferStateLayer”类型的 Surface 这个也是被 copy 到应用层的Surface ,说明应用层的数据是被绘制在这个 Surface上 的。于是 dump 了层级树的信息。其实 WMS 对窗口的管理也是和 View 管理的一样的,窗口有添加移除,或者屏幕旋转等场景,为了确保手机屏幕上各个窗口处在正确的位置,显示正确的大小。

芸兮的博客 4186

unity游戏开发日志(一)将mmd模型导入unity,并解决材质丢失的问题

unity音乐游戏开发,导入角色模型并解决材质问题

yizhigou1的博客 1765

activity及其窗口显示流程

activity 窗口显示

qq_33942765的博客 2333

禾赛PandarXT-16/阿努比LpmsIG1运行lio-sam

课题是多传感器融合,将GNSS/INS/LIDAR做融合定位导航,故考虑使用lio-sam开源算法,在此记录一下我在适配传感器数据时遇到的一些问题;

qq_44705939的博客 2966

AMBA总线协议(5)——AHB(三):猝发传输

在本文中我们展现了AHB猝发传输的具体细节,学习了猝发的类型和具体传输方式,着重讲解了四拍回卷猝发,猝发是AHB传输中非常重要的一部分。

apple_53311083的博客 3642

【安卓12源码】WMS系列:addWindow 和 removeWindow流程

Window的属性定义在WindowManager的内部类LayoutParams中,了解Window的属性能够更好的理解WMS的内部原理。Window的属性有很多种,与应用开发最密切的有三种,它们分别是Type(Window的类型)、Flag(Window的标志)和SoftInputMode(软键盘相关模式)Window的类型有很多种,比如应用程序窗口、系统错误窗口、输入法窗口、PopupWindow、Toast、Dialog等等。

mike_jun的博客 2451

YOLO学习笔记 | YOLOv8与卡尔曼滤波实现目标跟踪与预测(附代码)

YOLOv8采用改进的CSPDarknet骨干网络和动态标签分配策略,提供高精度、实时的目标检测能力。使用IOU(交并比)或马氏距离作为代价矩阵,通过匈牙利算法匹配预测框与检测框,解决多目标ID分配问题。卡尔曼滤波通过状态方程和观测方程对目标运动建模,结合预测与观测数据优化状态估计。完整代码需结合具体场景调整参数,并补充匈牙利算法实现(可参考。匈牙利算法(Hungarian Algorithm)是解决。的高效方法,常用于目标跟踪中的。),作为跟踪的输入观测值。(将检测框与预测框匹配)。

尘世冰封的专栏 1253

WMS机制学习分析

01.快速了解WMS机制1.1 WMS是什么1.2 应用于那些场景1.3 WMS主要功能1.4 Window是什么1.5 WMS整体框架02.WMS核心流程2.1 WMS启动流程03.WMS流程分析3.1 Window添加View3.2 WMS核心职责3.3 WMS是如何启动3.4 WMS构造方法3.5 WMS窗口管理05.一些源码分析5.1 addView源码分析5.2 remove源码与解析。

杨充 1067

37、深入解析SCTP与RTP传输协议

本文深入解析了SCTP与RTP两种重要传输协议。SCTP提供可靠的多流数据传输,支持关联管理、选择性确认和错误处理,适用于高可靠性场景;RTP则专注于实时音视频数据的低延迟传输,配合RTCP实现质量监控。文章详细介绍了两种协议的数据结构、工作流程及应用场景,并对比其特性,帮助开发者根据可靠性、实时性和多流需求选择合适的协议。

time3的博客 87

AI智能体丨使用Coze一键生成中式养生视频,39 条作品涨粉 37.9 万!(附保姆级教程)

本文介绍如何利用扣子(Coze)AI智能体工作流高效制作中式养生短视频。该方案通过AI自动生成养生文案、古风插画素材、语音合成和视频剪辑,将传统制作流程从2-3小时缩短至1-2分钟。工作流包含文案创作、音频生成、图片素材制作和视频合成四大模块,采用大模型处理各环节内容,最终输出可直接导入剪映的草稿文件。特别适合希望快速批量制作文化氛围感强、兼具干货与视觉效果的养生内容创作者,效率提升近百倍。

李同学Lino的博客 3031

【Android View】窗口机制

Android专题 窗口机制

studyForMokey的博客 1061

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Android WMS核心机制实战:从零构建窗口管理系统模拟环境

窗口管理系统是图形用户界面的核心基础组件,负责管理屏幕上所有窗口的创建、布局、合成与显示。其核心原理在于通过统一的服务协调多个应用对显示资源的请求,维护窗口的层级关系、焦点状态和生命周期。在Android系统中,Window Manager Service(WMS)正是这一关键技术的实现,它作为连接应用层与显示硬件的桥梁,其稳定性和性能直接决定了系统的交互体验与多任务能力。理解WMS的底层机制,对于进行系统级定制、性能优化以及解决复杂的显示问题(如窗口闪烁、焦点丢失)具有极高的技术价值。尤其在车机、折叠屏等

weixin_30765505的博客 411

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

WMS的小问题

WindowManagerService 是 Android 系统中的一个系统服务,它负责管理所有窗口的显示和操作,因此 mWindowMap 变量的访问和修改都是在 WindowManagerService 的上下文中进行的。在处理窗口创建的过程中,WMS需要与UI线程进行交互,以便实时更新窗口的显示状态。相比于新开一个线程来处理窗口创建的过程,使用Handler的runWithScissors方法可以避免线程切换的开销和资源浪费,同时也可以确保对UI线程的访问是线程安全的,避免了可能出现的并发问题。

m0_54010212的博客 302

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Android强制系统横屏的原理和实现

一、Android屏幕相关的知识 Android横竖屏设置 Android设置横竖屏的入口多种多样,如下: 1、Activity窗口:应用Mainfest中配置screenOrientation参数、Activity中调用setRequestedOrientation(),这是通过设置Activity的screenOrientation属性 2、系统栏屏幕自动旋转:使用systemui包中的RotationLockTile类的handleClick()方法设置的 3、非Activity窗口:指定W

qq_36754698的博客 6916

【窗口篇】windowState

WindowState 是 Android 窗口管理的“状态核心”,它存储了窗口的所有关键信息,是 WMS 实现窗口布局、调度、渲染的基础。对于应用开发者而言,虽然无法直接操作 WindowState,但理解其核心职责(状态管理、权限校验、渲染衔接)能帮助更好地排查窗口相关问题(如悬浮窗无法显示、窗口位置异常、多窗口适配问题);对于系统开发者而言,WindowState 是定制窗口管理逻辑(如修改窗口层级、新增窗口类型)的核心切入点。GPT : 好的,我们来介绍一下这个类。在 Android 系统的。

疯子与天才就在一念之间 1119

WindowManager源码分析-从悬浮窗说起

android源码 ,WindowManager,悬浮窗

hyc1988107的博客 1464

Window,View,View的绘制流程 ,自定义View ,自定义属性

View

weixin_43836998的博客 702

Android深入解析WindowManager

WindowManager体系关系 我们这里从Window(这里Window是个抽象概念)开始了解WindowManager,这些window都会与WindowManager建立关联,比如Activity、Toast、Dialog、PopupWindow等。 Activity中 PopupWindow中 那么这个WindowManager为何有如此大作用呢...

weixin_40929353的博客 371
上一篇: 安卓WMS层面分析窗口的位置变化-安卓framework实战开发
下一篇: Miracast通用投屏与厂商自定义投屏优缺点对比分析
千里马学框架
博客等级 码龄6年 1万+粉丝 651原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值