【大道至简】官方兼容到android13+的获取系统屏幕高度, statusbar,navBar

android在屏幕高度和app高度,statusbar, navigationbar的高度处理上,迭代了好多版本。
android11, android12都有新的api和过时的api标记。

涉及的api类似如下:
windowManager,defaultDisplay, Context.display, DecorView, windowInsets, Compat兼容库, getRealSize, getSize,
currentWindowMetrics, maximumWindowMetrics, 通过resources获取资源id navigation_bar_height等等等等。

网上的帖子跟api一样,实现的五花八门太多了。

花了2天时间,终于找到了官方,而且最合适的方案:
全网似乎都没有这么简洁和准确的方案了:
implemention “androidx.window:window:1.2.0” 引入后,写上下面2个函数:

//随意调用,官方出品最精简,最准确。
fun Activity.getScreenFullSize() : Pair<Int, Int> {val m = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this)//computeMaximumWindowMetrics(this) 区别就是多屏,类似华为推上去的效果。不分屏就是一样的。return m.bounds.width() to m.bounds.height()
}/**
* 获取当前的statusBar的高度和navigationBar高度。如果在onCreate,onStart, onResume调用,必须经过一轮View.post之后。
* 如果你明确知道activity已经ok则直接调用。
*/
fun Activity.currentStatusBarAndNavBarHeight() : Pair<Int, Int>? {val insets = ViewCompat.getRootWindowInsets(window.decorView) ?: return nullval nav = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottomval sta = insets.getInsets(WindowInsetsCompat.Type.statusBars()).topreturn sta to nav
}

接下来介绍一下:

想要屏幕高宽

getScreenFullSize() 即 WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity)

无需等待界面渲染成功,即在onCreate就可以调用,而且里面已经做了低版本兼容,感谢jetpack window库
获取的就是整个屏幕的高度。包含了statusBar,navigationBar的高度一起。与adb shell wm size一致。
这个方法100%可靠。虽然我们看api上描述说低版本(由于navigationBar可能获取不到)近似值,但也是最接近最合理的值,不会是0的。所以这个函数就是目前集大成者。
点击computeCurrentWindowMetrics进入查看源码:

 val bounds = if (Build.VERSION.SDK_INT >= VERSION_CODES.R) {currentWindowBounds(activity) //往下就是wm.currentWindowMetrics.bounds} else if (Build.VERSION.SDK_INT >= VERSION_CODES.Q) {computeWindowBoundsQ(activity) //反射Configuration windowConfiguration bounds} else if (Build.VERSION.SDK_INT >= VERSION_CODES.P) {computeWindowBoundsP(activity) //反射Configuration windowConfiguration bounds} else if (Build.VERSION.SDK_INT >= VERSION_CODES.N) {computeWindowBoundsN(activity) //display realSize + navigationHeight Id获取} else {computeWindowBoundsIceCreamSandwich(activity)}

由此可见,这个就是集大成者。
大家放心使用getScreenFullSize,WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this),来获取屏幕的高宽。官方出品最精简,最准确。

想要SystembarHeight和navBarHeight

大家一般都见过这个代码:

fun Window.transparentStatusBar(isBlackStatusBarTextColor: Boolean? = null,isBlackNavigationBarTextColor: Boolean? = null,crossinline insetsBlock: (insets: WindowInsetsCompat,statusBarsHeight: Int,navigationBarHeight: Int) -> WindowInsetsCompat = {insets, _, _ -> insets}
) {ViewCompat.setOnApplyWindowInsetsListener(decorView) { _, insets ->val bottom = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottomval top = insets.getInsets(WindowInsetsCompat.Type.statusBars()).topinsetsBlock.invoke(insets,top,bottom)}WindowCompat.setDecorFitsSystemWindows(this, false)statusBarColor = Color.TRANSPARENTif (isBlackStatusBarTextColor != null || isBlackNavigationBarTextColor != null) {WindowCompat.getInsetsController(this, decorView).apply {if (isBlackStatusBarTextColor != null) {isAppearanceLightStatusBars = isBlackStatusBarTextColor}if (isBlackNavigationBarTextColor != null) {isAppearanceLightNavigationBars = isBlackNavigationBarTextColor}}}
}

我们经过用上述代码来做沉浸式。就是程序在statusBar之下,也可以在navigationBar之下。更加延展。
这里其实有2个注意点:
这个函数如果不调用
WindowCompat.setDecorFitsSystemWindows(this, false) 对于constraintLayout是不会回调的。他默认fitsystemWindow。
我们如果仅仅ViewCompat.setOnApplyWindowInsetsListener是不一定有回调的。

所以使用注意事项:

  1. 你如果做了沉浸式,即调用了WindowCompat.setDecorFitsSystemWindows(this, false) + setOnApplyWindowInsetsListener,则可以在回调监听获取
        val bottom = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom //navBarHeightval top = insets.getInsets(WindowInsetsCompat.Type.statusBars()).top //statusbarHeight
  1. 你如果没有做沉浸式或者setOnApplyWindowInsetsListener不生效,那么调用currentStatusBarAndNavBarHeight().
    即,ViewCompat.getRootWindowInsets(window.decorView)
    他的说明文档,写了,必须在view Attach到屏幕上,即view.post的执行,就是attach之后运行的。有兴趣可以研究View的post逻辑源码。
    如果明确已经准备好,则无需post了。也就是在onCreate,onResume使用该函数必须post。

  2. 唯一缺点就是,不能动态监听。这也不能说是缺点,他本意就是一次获取。使用场景就是这样。如果你要动态监听,还是类似实现透明一样,通过WindowCompat.setDecorFitsSystemWindows(this, false) + setOnApplyWindowInsetsListener监听实现。

其他备注:

windowManager.currentWindowMetrics和MaximumWindowMetrics的区别:
max永远是屏幕大小。
current就是当前窗口,其实也是包含了statusBar和navigationBar的。但是当多窗口模式,或者分屏,比如华为有这个悬浮应用功能,获取到的current就是变化后的。
请添加图片描述

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

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

相关文章

分布式光伏监控系统功能模块详解

目前&#xff0c;分布式光伏发电系统的总容量比较小&#xff0c;并且光伏电站的功率受外界环境影响容易出现大起大落的现象。这使电压调整变得很困难。光伏电站运行维护人员不足&#xff0c;长时间不保养维护会影响光伏电站的发电效率。针对上述问题&#xff0c;鹧鸪云基于无线…

RK3588 camera驱动总结一

RK3588的硬件能力 ISP和VICAP的链接关系&#xff1a; VICAP和ISP是独立的两个图像处理IP, VICAP所采集图像若要通过ISP处理&#xff0c;在驱动层面需要生成VICAP对应接口的v4l2 sub device链接到ISP对应的节点&#xff0c;以提供参数给ISP驱动使用。 1.RKISP 驱动 RKISP驱动主…

java内容快速回顾+SSM+SpringBoot简要概述

文章目录 java基础知识基本知识列表面对对象堆与栈的关系值修改与引用修改异常&#xff1a;错误异常 SSMspringMVCServletSpringMVC&#xff1a;基于 Servlet的 Spring Web 框架&#xff0c; spring控制反转 IoC(Inversion of Control)面向切面 Aop MybatisJDBCMybatis SpringB…

C++ QT设计模式 (第二版)

第3章 Qt简介 3.2 Qt核心模块 Qt是一个大库&#xff0c;由数个较小的库或者模块组成&#xff0c;最为常见的如下&#xff1a;core、gui、xml、sql、phonon、webkit&#xff0c;除了core和gui&#xff0c;这些模块都需要在qmake的工程文件中启用 QTextStream 流&#xff0c;Qdat…

深入了解 npm:Node.js 包管理工具详解

文章目录 一、npm 基本概念1.1 什么是 npm&#xff1f;1.2 package.json 文件 二、npm 常用命令2.1 初始化项目2.2 安装依赖2.2.1 安装单个包2.2.2 全局安装包2.2.3 安装开发依赖 2.3 移除依赖2.4 更新依赖2.5 查看已安装的包2.6 发布包 三、npm 高级用法3.1 使用 npm scripts3…

电源模块效率的正确测试方法

电源效率是评价电源性能的重要指标&#xff0c;它直接关系到设备的稳定性和能源的利用效率。因此&#xff0c;对电源进行效率测试显得尤为重要。电源在工作过程中&#xff0c;会有部分能量损耗&#xff0c;因此&#xff0c;电源效率的高低&#xff0c;不仅影响着设备的性能&…

一篇文章带你入门CSRF

1.什么是CSRF 用一个形象生动的比喻就是&#xff1a; 你给朋友的房子留下了备用钥匙&#xff0c;但是有人偷偷拿走了这把钥匙&#xff0c;然后用这把钥匙进入了你朋友的房子并做了各种坏事。你朋友以为只有你能使用这把钥匙&#xff0c;所以没对任何操作产生怀疑。 在这个比…

C++自定义日期类的精彩之旅(详解)

在学习了C的6个默认成员函数后&#xff0c;我们现在动手实现一个完整的日期类&#xff0c;来加强对这6个默认成员函数的认识。 这是日期类中所包含的成员函数和成员变量&#xff1a; 构造函数 // 函数&#xff1a;获取某年某月的天数 inline int GetMonthDay(int yea…

VictoriaMetrics

概念 介绍 VictoriaMetrics&#xff0c;是一个快速高效、经济并且可扩展的监控解决方案和时序数据库 本文均用VM简称VictoriaMetric 作用 用于作为prometheus的长期储存方案&#xff0c;代替prometheus存储监控采集的数据 优点 远程存储&#xff1a;可作为单一或多个Pro…

Python中tkinter编程入门4

在Python中tkinter编程入门3-CSDN博客中创建了Button控件&#xff0c;点击该控件就会产生一个点击事件&#xff0c;在创建Button控件时指定该点击事件的处理程序后&#xff0c;按键控件就会对用户的点击事件产生响应。 1 定义事件处理器 定义事件处理器就是一个自定义的函数。…

matlab使用1-基础

matlab使用1-基础 文章目录 matlab使用1-基础1. 界面介绍2. matlab变量3. matlab数据类型4. matlab矩阵操作5. matlab程序结构5.1 顺序结构5.2 循环结构5.3 分支结构 1. 界面介绍 命令行窗口输入&#xff1a;clc 可清除命令行窗口command window的内容 clc命令行窗口输入&…

【知识拓展】大白话说清楚:IP地址、子网掩码、网关、DNS等

前言 工作中常听别人说的本地网络是什么意思&#xff1f;同一网段又是什么意思&#xff1f;它俩有关系吗&#xff1f; 在工作中内经常会遇到相关的网络问题&#xff0c;涉及网络通信中一些常见的词汇&#xff0c;如IP地址、子网掩码、网关和DNS等。具体一点&#xff1a;经常会…