Android窗口层级(Window Type)分析

前言

Android的窗口Window分为三种类型:

应用Window,比如ActivityDialog;子Window,比如PopupWindow;系统Window,比如Toast、系统状态栏、导航栏等等。

应用Window的Z-Ordered最低,就是在系统中的显示层级最低,然后到子Window,层级最高的是系统Window。层级高的Window会覆盖层级低的Window。 要让窗口覆盖显示,只需要使它的层级比上个窗口高。

三种窗口对应不同的WindowToken,每个应用组件(应用组件可以是ActivityInputMethodWallpaper等,每个组件对应一个WindowToken)都需要通过WindowToken向WMS申请添加窗口,WMS(WindowManagerSerivce)通过根据窗口的WindowToken进行分类组织,相同WindowToken的窗口紧密联系。应用组件在新建窗口时必须提供WindowToken表面窗口身份类型。系统窗口会隐式申明WindowToken,同时WMS会在addWindow()时进行鉴权。

应用窗口层级

Activity的显示

先从ActivitysetContentView()的源码入手:
在这里插入图片描述
AppCompatDelegateImpl源码中
在这里插入图片描述

mSubDecor并非Window中的DecorView,在创建DecorView之后创建的一个子DecorView,包括是否是包含ActionBarFloatingActionButton等,相当于旧版本的DecorViewTitleBar

getWindow()是返回返回ActivitymWindow变量,指向一个Window的对象,Window是一个抽象类,这里返回的是PhoneWindow对象(PhoneWindowWindow的子类),PhoneWindow中有一个DecorView对象,DecorView实际上就是个FrameLayoutsetContentView()的子布局最终会添加到DecorView中,DecorView为当前窗口的根视图。

这个根视图是如何最终被绘制出来的?

Window表示一个抽象窗口的概念,是View的直接管理者,对应一个ViewWindowView之间由ViewRootImpl联系。

ActivityView层级就是如下:
在这里插入图片描述

应用窗口层级类型

WMS在进行应用窗口叠加时,会动态改变应用窗口的层值,但层值不会大于99。

public static final int FIRST_APPLICATION_WINDOW = 1;
public static final int TYPE_BASE_APPLICATION = 1;
public static final int TYPE_APPLICATION = 2;
public static final int TYPE_APPLICATION_STARTING = 3;
public static final int TYPE_DRAWN_APPLICATION = 4;
public static final int LAST_APPLICATION_WINDOW = 99;

1.Activity的默认窗口层级为TYPE_BASE_APPLICATION。通过WindowManager.addView()DecorView添加到窗口中。在ActivityThread中有这样一段代码:

在这里插入图片描述
2.Dialog默认的层级为TYPE_APPLICATION
Dialog的创建:
1.创建Window(方法同Activity创建);
2.初始化DecorView,并将Dialog的视图添加进DecorView
3.将DecorView添加到Window中显示。
同为TYPE_APPLICATION层级的也有ActionMode
WindowmanagerLayoutParams构造方法如果不指定windowtype默认为TYPE_APPLICATION,所以DialogActivity中创建时不指定窗口层级默认为TYPE_APPLICATION
在这里插入图片描述
Service中创建Dialog并弹出时,跟Activity同样代码会报错。需要设置为WindowManager.LayoutParams.TYPE_SYSTEM_ALERT的系统窗口层级以上才可以正常显示。

3.TYPE_APPLICATION_STARTING 启动窗口,Z-Ordered应高于应用程序中的所有其他窗口。为Android12特有的启动画面StartingWindow 即包含SplashScreen。这里还涉及到SystemUI的WMShell组件,其中SplitScreen分屏模式、OneHanded单手模式、Freeform自由窗口模式、Bubble气泡通知窗口(Android Q)、PIP画中画模式等等系统模式窗口为WMShell处理的一部分。

  1. 经常在应用中做一些Toast临时弹框,但Toast为系统窗口而不是应用窗口,层级为TYPE_TOAST,不在应用窗口的范畴。在下面系统窗口介绍。

子窗口层级(Sub Window)

       public static final int FIRST_SUB_WINDOW = 1000;public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW + 4;public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;public static final int LAST_SUB_WINDOW = 1999;

子窗口类型必须设置为应用窗口附加的窗口。 这些类型的窗口在 Z-Ordered中保持在它们附加的窗口旁边,并且它们的坐标是相对于所附加的应用窗口。

1.TYPE_APPLICATION_PANEL为面板子窗口,应用窗口顶部的面板,例如PopupWindow
PopupWindow源码中指定的窗口层级:

  private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;

2.TYPE_APPLICATION_MEDIA显示媒体(如视频)的窗口。为Android 7.1之前的SurfaceView源码中默认的层级,在SurfaceView源码中的setZOrderOnTop()方法,设置SurfaceView的显示顺序。

  public void setZOrderOnTop(booleanonTop) {if (onTop) {mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;// ensures the surface is placed below the IMEmLayout.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;} else {mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;mLayout.flags&= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;}}

3.TYPE_APPLICATION_MEDIA_OVERLAY为隐藏的类型,应用程序无法直接调用。同样在Android 7.1之前的SurfaceView源码中涉及:

       public void setZOrderMediaOverlay(booleanisMediaOverlay) {mWindowType = isMediaOverlay? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY: WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;}

4.TYPE_APPLICATION_SUB_PANEL应用窗口的子面板,代表在TYPE_APPLICATION_PANEL的上层,例如PopupWindow弹出列表或者弹出Editor等编辑框等等。

5.TYPE_APPLICATION_ATTACHED_DIALOG类似于TYPE_APPLICATION_PANEL,但窗口的布局是作为顶级窗口的布局发生的,而不是作为其容器的子窗口。例如CharacterPickerDialog。在PhoneWindow源码中的openPanel()方法使用的就是这个类型,在Android7.1以上则不同,两个值都小于0 代表在当前显示窗口的下层:
在这里插入图片描述
6.TYPE_APPLICATION_ABOVE_SUB_PANEL隐藏的类型,为应用窗口之上的子面板及其子面板窗口。 这些窗口显示在其附加窗口和任何 TYPE_APPLICATION_SUB_PANEL 面板的顶部。

系统窗口层级

在开发过程中,经常这样添加窗口:

mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 
mLayoutParams = new WindowManager.LayoutParams(); 
mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 
mLayoutParams.format = PixelFormat.RGBA_8888; 
mLayoutParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; mLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 
mLayoutParams.type = WindowManager.LayoutParams. TYPE_APPLICATION_OVERLAY;
mWindowManager.addView(view, mLayoutParams);

注:TYPE_APPLICATION_OVERLAY为Android 8加入的类型

这样添加的窗口都为系统窗口,同时也需要窗口权限。

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

下面为系统窗口层级类型:

窗口类型描述
FIRST_SYSTEM_WINDOW系统的窗口类型,起始值2000
TYPE_STATUS_BAR状态栏。只能有一个状态栏窗口;在屏幕的顶部,所有其他窗口都向下移动,所以它们在屏幕的下面。可通过参数设置全屏。
TYPE_SEARCH_BAR搜索栏。只能有一个搜索栏窗口;在屏幕的顶部。在StatusBar上显示
TYPE_PHONE电话窗口,例如来电通话。在应用窗口之上,但位于状态栏的后面。已过时,用TYPE_APPLICATION_OVERLAY替代
TYPE_SYSTEM_ALERT系统警告窗口,如低电量警告弹框。已过时,用TYPE_APPLICATION_OVERLAY替代。
TYPE_KEYGUARD锁屏窗口。不生成引用的接口。
TYPE_TOASTToast临时通知窗口。已过时,用TYPE_APPLICATION_OVERLAY替代。
TYPE_SYSTEM_OVERLAY系统覆盖窗口,需要显示在其他所有窗口之上。这些窗口不能进行输入聚焦,否则会干扰锁屏。已过时,用TYPE_APPLICATION_OVERLAY替代。
TYPE_PRIORITY_PHONE优先手机UI,即使锁屏处于活动状态也需要显示。这些窗口不能进行输入聚焦,否则会干扰锁屏。已过时,用TYPE_APPLICATION_OVERLAY替代。
TYPE_SYSTEM_DIALOG从状态栏滑出的面板。
TYPE_KEYGUARD_DIALOG锁屏时显示的对话框。
TYPE_SYSTEM_ERROR系统错误窗口。已过时,用TYPE_APPLICATION_OVERLAY替代。
TYPE_INPUT_METHOD输入法窗口,显示在正常UI上方。可以调整应用程序窗口的大小或平移,以在显示该窗口时保持输入焦点可见。
TYPE_INPUT_METHOD_DIALOG输入法对话框窗口,显示在当前输入法窗口上方。
TYPE_WALLPAPER壁纸窗口。放在任何想在壁纸上的窗口后面显示的层级上。系统有壁纸服务,跟过壁纸对应的TOKEN对窗口进行特殊调节
TYPE_STATUS_BAR_PANEL从状态栏上滑出的面板,例如SystemUIDialog,SystemUI的HeadsUpView。不生成的APP使用的类型
TYPE_SECURE_SYSTEM_OVERLAY安全系统覆盖窗口,需要显示在其他所有窗口之上。这些窗口不能进行输入聚焦,否则会干扰锁屏。这与TYPE_SYSTEM_OVERLAY完全相同,只是只允许系统本身创建这些覆盖。应用程序无法获得创建安全系统覆盖的权限。隐藏的类型
TYPE_DRAG拖放伪窗口。最多只有一个拖动层,并且它被放置在所有其他窗口的顶部。隐藏的类型
TYPE_STATUS_BAR_SUB_PANEL从状态栏上滑出的面板显示在所有用户的窗口上。这些窗口显示在状态栏和任何TYPE_STATUS_BAR_PANEL窗口的顶部。例如SystemUIDialog通过setWindowOnTop()方法切换TYPE_STATUS_BAR_PANEL的TYPE_STATUS_BAR_SUB_PANEL显示层级。隐藏的类型
TYPE_POINTER鼠标指针。隐藏的类型
TYPE_NAVIGATION_BAR导航栏。隐藏的类型
TYPE_VOLUME_OVERLAY用户更改系统音量时显示的音量级别对话框。隐藏的类型
TYPE_BOOT_PROGRESS启动进度对话框,位于所有内容的顶部。隐藏的类型
TYPE_INPUT_CONSUMER当系统UI栏被隐藏时,使用输入事件的窗口类型。隐藏的类型
TYPE_NAVIGATION_BAR_PANEL导航栏面板(当导航栏不同于状态栏时)。隐藏的类型
TYPE_DISPLAY_OVERLAY显示覆盖窗口。用于模拟辅助显示设备。隐藏的类型
TYPE_MAGNIFICATION_OVERLAY放大叠加窗口。当启用可访问性放大时,用于突出显示显示器的放大部分。隐藏的类型
TYPE_PRIVATE_PRESENTATION私有顶部的演示Presentation窗口。Presentation会根据对应的Display的参数FLAG_PRIVATE来配置。
TYPE_VOICE_INTERACTION语音交互窗口。隐藏的类型
TYPE_ACCESSIBILITY_OVERLAY由连接的AccessibilityService覆盖的窗口,用于拦截用户交互,而无需更改可访问性服务可以内省的窗口。特别是,可访问性服务只能内省有视力的用户可以与之交互的窗口,即他们可以触摸这些窗口或在这些窗口中键入内容。例如,如果有一个可触摸的全屏辅助功能覆盖,则辅助功能服务将对其下方的窗口进行内省,即使它们被可触摸窗口覆盖。
TYPE_VOICE_INTERACTION_STARTING语音交互层的启动窗口。
TYPE_DOCK_DIVIDER用于显示用于调整堆栈大小的句柄的窗口。此窗口由系统进程所有。隐藏的类型
TYPE_QS_DIALOG类似于 TYPE_APPLICATION_ATTACHED_DIALOG,但由快速设置平铺使用。隐藏的类型
TYPE_SCREENSHOT屏幕截图。截取之下的窗口层级。如果采用android远程的层级截图无法截取倒车相关的UI视图。隐藏接口。
TYPE_PRESENTATION外部显示器上的演示窗口。隐藏的类型
TYPE_APPLICATION_OVERLAY用程序覆盖窗口显示在所有活动窗口上方(类型介于 FIRST_APPLICATION_WINDOW和 LAST_APPLICATION_WINDOW之间),但显示在状态栏或IME等关键系统窗口下方。系统可以随时改变这些窗口的位置、大小或可见性,以减少用户的视觉混乱,并管理资源要android.Manifest.permissionSYSTEM_ALERT_WINDOW权限。系统将调整具有此窗口类型的进程的重要性,以减少低内存杀手杀死它们的机会
TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY用于在其他窗口之上添加辅助功能窗口放大倍数的窗口。这将把窗口放置在覆盖窗口中。隐藏的类型
TYPE_NOTIFICATION_SHADE锁屏时通知效果。只能有一个状态栏窗口;它被放置在屏幕的顶部,所有其他窗口都向下移动,所以它们都在屏幕的下面。隐藏的类型
TYPE_STATUS_BAR_ADDITIONAL用于在屏幕的非常规部分(即屏幕的左侧或底部)显示状态栏。隐藏的类型
LAST_SYSTEM_WINDOW系统窗口类型最高层级2999

下面为Android1开始的窗口层级,从最初的10多个发展到如今的40多个,层出不穷。
在这里插入图片描述

自定义的窗口层级

车载方案存在倒车等特殊界面需要在较高的窗口层级显示,Android原有的窗口层级不满足车载需求,因此都会自定义车载窗口层级。

下图为参考自定义的窗口层级:
在这里插入图片描述

系统可以自定义窗口层级,framework修改参考另一篇博客:
android自定义窗口层级(自定义车载系统中倒车影像显示层级)

自定义窗口层级在不同Android版本中的初始层级值也是不同,因此需要通过系统属性SystemProperties.getInt("ro.custom.window", 2041)来判断初始值。
例如在Android 13平台的默认ro.custom.window 属性为2401,在Andoid 9等平台为2031。这样做的目的是由于跟Android原生的窗口层级存在冲突,因此需要根据平台来调节初始值。
TYPE_CUSTOM_FIRST_WINDOW()为自定义初始的系统窗口层级,在Android原生的窗口层级之上

TYPE_TOP_BARTYPE_BOTTOM_BARTYPE_CUSTOM_FIRST_WINDOW之上,但在倒车界面之下显示。
TYPE_REVERSE_WINDOW倒车影像为的窗口层级。若要覆盖在倒车之上需要使用更高的层级或者在倒车出现后添加TYPE_CUSTOM_LAST_WINDOW

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uni-app 使用uCharts-进行图表展示(折线图带单位)

前言 在uni-app经常是需要进行数据展示&#xff0c;针对这个情况也是有人开发好了第三方包&#xff0c;来兼容不同平台展示 uCharts和pc端的Echarts使用差不多&#xff0c;甚至会感觉在uni-app使用uCharts更轻便&#xff0c;更舒服 但是这个第三方包有优点就会有缺点&#xf…

医院安全不良事件报告系统源码 PHP+ vue2+element+ laravel8+ mysql5.7+ vscode开发

不良事件上报系统通过 “事前的人员知识培训管理和制度落地促进”、“事中的事件上报和跟进处理”、 以及 “事后的原因分析和工作持续优化”&#xff0c;结合预存上百套已正在使用的模板&#xff0c;帮助医院从对护理事件、药品事件、医疗器械事件、医院感染事件、输血事件、意…

数字人员工成企业得力助手,虚拟数字人为企业注入高科技基因

随着互联网和人工智能技术的快速发展&#xff0c;以“数字员工”为代表的数字生产力&#xff0c;正在出现在各行各业的业务场景中。数字人员工的出现不是替代人类&#xff0c;而是通过技术提高工作效率&#xff0c;实现更加智能化的服务体验&#xff0c;帮助企业实现大规模自动…

网上企业订货系统功能列表介绍|企业APP订单管理软件

网上企业订货系统功能列表介绍|企业APP订单管理软件 后台功能列表 &#xff08;后台支持手机版本 订货APP,管理订单的APP&#xff09; 后台登陆 输入账号密码登录企业订货管理软件系统 后台首页 显示近日,月,年订单统计&#xff0c;和收款欠款等统计。 订单模块 新建订单 …

人脸识别三部曲

人脸识别三部曲 首先看目录结构图像信息采集 采集图片.py模型训练 训练模型.py人脸识别 人脸识别.py效果 首先看目录结构 引用文121本 opencv │ 采集图片.py │ 训练模型.py │ 人脸识别.py │ └───trainer │ │ trainer.yml │ └───data │ └──…

使用 Sealos 一键部署高可用 MinIO,开启对象存储之旅

大家好&#xff01;今天这篇文章主要向大家介绍如何通过 Sealos 一键部署高可用 MinIO 集群。 MinIO 对象存储是什么&#xff1f; 对象是二进制数据&#xff0c;例如图像、音频文件、电子表格甚至二进制可执行代码。对象的大小可以从几 B 到几 TB 不等。像 MinIO 这样的对象存储…

零基础学前端(三)重点讲解 HTML

1. 该篇适用于从零基础学习前端的小白 2. 初学者不懂代码得含义也要坚持模仿逐行敲代码&#xff0c;以身体感悟带动头脑去理解新知识 3. 初学者切忌&#xff0c;不要眼花缭乱&#xff0c;不要四处找其它文档&#xff0c;要坚定一个教授者的方式&#xff0c;将其学通透&#xff…

家政服务接单小程序开发源码 家政保洁上门服务小程序源码 开源完整版

分享一个家政服务接单小程序开发源码&#xff0c;家政保洁上门服务小程序源码&#xff0c;一整套完整源码开源&#xff0c;可二开&#xff0c;含完整的前端后端和详细的安装部署教程&#xff0c;让你轻松搭建家政类的小程序。家政服务接单小程序开发源码为家政服务行业带来了诸…

shell脚本学习笔记02(小滴课堂)

可以在home目录下创建一个shell.sh文件。 按w进入命令行模式。按i进入插入模式。如果想返回命令行模式&#xff0c;按esc即可。然后可以使用x和dd进行删除内容。 在插入模式下我们点击esc键&#xff0c;再去按:键&#xff0c;我们就可以进入到底行模式了&#xff1a; 可以设…

518抽奖软件,可生成几排几列的号码座号

518抽奖软件简介 518抽奖软件&#xff0c;518我要发&#xff0c;超好用的年会抽奖软件&#xff0c;简约设计风格。 包含文字号码抽奖、照片抽奖两种模式&#xff0c;支持姓名抽奖、号码抽奖、数字抽奖、照片抽奖。(www.518cj.net) 生成号码/座号 入口&#xff1a; 主界面上点…

基于深度学习的加密恶意流量检测

加密恶意流量检测 研究目标定位数据收集数据处理基于特征分类算法的数据预处理基于源数据分类算法的数据预处理 特征提取模型选择基于数据特征的深度学习检测算法基于特征自学习的深度学习检测算法 训练和评估精确性指标实时性指标 应用检验改进 摘录自&#xff1a;Mingfang ZH…

ZABBIX 6.4官方安装文档

一、官网地址 Zabbix&#xff1a;企业级开源监控解决方案 二、下载 1.选择您Zabbix服务器的平台 2. Install and configure Zabbix for your platform a. Install Zabbix repository # rpm -Uvh https://repo.zabbix.com/zabbix/6.4/rhel/8/x86_64/zabbix-release-6.4-1.el8…

【实战】H5 页面同时适配 PC 移动端 —— 旋转横屏

文章目录 一、场景二、方案三、书单推荐01 《深入实践Kotlin元编程》02 《Spring Boot学习指南》03 《Kotlin编程实战》 一、场景 一个做数据监控的单页面&#xff0c;页面主要内容是一个整体必须是宽屏才能正常展示&#xff0c;这时就不能用传统的适配方案了&#xff0c;需要…

前端设计模式基础笔记

前端设计模式是指在前端开发中经常使用的一些解决问题的模式或思想。它们是经过实践证明的最佳实践&#xff0c;可以帮助我们更好地组织和管理我们的代码。 一、单例模式&#xff08;Singleton Pattern&#xff09; 单例模式是一种创建型模式&#xff0c;它保证一个类只有一个…

mysql远程连接失败

先上结论&#xff0c;只提出最容易忽略的地方 服务器是阿里云、腾讯云等平台&#xff0c;平台本身自带的防火墙没有开启iptables规则中禁用了3306&#xff0c;即使你根本没有启用iptables服务 第二条是最离谱的 从这里可以看到&#xff0c;我服务器并未启用 iptables 服务 但…

Java8实战-总结24

Java8实战-总结24 用流收集数据收集器简介收集器用作高级归约预定义收集器 用流收集数据 流可以用类似于数据库的操作帮助你处理集合。可以把Java 8的流看作花哨又懒惰的数据集迭代器。它们支持两种类型的操作&#xff1a;中间操作(如filter或map)和终端操作(如count、findFir…

互联网医院App开发:构建医疗服务的技术指南

互联网医院App的开发是一个复杂而具有挑战性的任务&#xff0c;但它也是一个充满潜力的领域&#xff0c;可以为患者和医疗专业人员提供更便捷的医疗服务。本文将引导您通过一些常见的技术步骤来构建一个简单的互联网医院App原型&#xff0c;以了解该过程的基本概念。 技术栈选…

JWT 安全及案例实战

文章目录 一、JWT (json web token)安全1. Cookie&#xff08;放在浏览器&#xff09;2. Session&#xff08;放在服务器&#xff09;3. Token4. JWT (json web token)4.1 头部4.1.1 alg4.1.2 typ 4.2 payload4.3 签名4.4 通信流程 5. 防御措施 二、漏洞实例&#xff08;webgoa…

【TCPDF】使用TCPDF导出PDF文件

目录 一、安装TCPDF类库 二、安装字体 三、使用TCPDF导出PDF文件 目的&#xff1a;PHP通过TCPDF类库导出文件为PDF。 开发语言及类库&#xff1a;ThinkPHP、TCPDF 效果图如下 一、安装TCPDF类库 在项目根目录使用composer安装TCPDF&#xff0c;安装完成后会在vendor目录下…

开发调试:提高代码质量与开发效率的关键步骤

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 引言 在现代软件开发中…