号外!号外!全网第一手Android P刘海屏适配大揭秘,唯一Kotlin算法

news2025/4/27 3:46:58

如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.2.适配刘海屏

在刘海屏调试打开之后,浏览应用的所有页面,测试所有遮挡问题,或者是下移导致的问题,对有问题的页面进行布局适配。适配方案如下:

Google 提供的适配方案,可以设置是否在全屏模式下,使用刘海屏的区域。

// 谷歌官方提供的默认适配刘海屏
val attrib = window.attributes
attrib.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS

新的布局属性layoutInDisplayCutoutMode包含三种可选的模式,分别为:

// 窗口声明使用刘海区域
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 1;
// 默认情况下,全屏窗口不会使用到刘海区域,非全屏窗口可正常使用刘海区域
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0;
// 声明不使用刘海区域
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2;

4.3.刘海屏的高度

在全屏模式下,我们的应用页面背景充满整个屏幕显示,控件和文字等关键信息布局在状态栏以外的区域,以保证关键信息不会出现遮挡(谷歌要求:凹槽高度和刘海高度要保持一致)。我们需要有办法获取到刘海屏凹槽的高度,才可以做到设计和布局的时候,留出安全距离。

4.3.1. 获取刘海尺寸信息接口

Android P已经预留出了标准的测量刘海屏凹槽的Api:DisplayCutout。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

刘海屏的凹槽,就在屏幕的中间,所以只有**getSafeInsetTop()方法返回的结果,是我们需要的,而其他的getSafeInsetXXX()**方法,直接返回的是0。代码如下所示:

btn_always.postDelayed(Runnable {

val displayCutout = btn_always.rootWindowInsets.displayCutout
if (null == displayCutout) {
Log.e(TAG, “displayCutout is empty”)
return@Runnable
}
Log.i(TAG, “SafeInsetBottom:” + displayCutout.safeInsetBottom);
Log.i(TAG, “SafeInsetLeft:” + displayCutout.safeInsetLeft);
Log.i(TAG, “SafeInsetRight:” + displayCutout.safeInsetRight);
Log.i(TAG, “SafeInsetTop:” + displayCutout.safeInsetTop);

}, 100)

输出结果为:

SafeInsetBottom:0
SafeInsetLeft:0
SafeInsetRight:0
SafeInsetTop:84

4.3.2. 获取系统状态栏高度接口

获取刘海屏的高度之后,我们还要获取系统状态栏的高度,代码如下:

fun getStatusBarHeight(context: Context): Int {

var result = 0

val resourceId = context.resources.getIdentifier(“status_bar_height”, “dimen”, “android”)
if (0 < resourceId) {
result = context.resources.getDimensionPixelOffset(resourceId)
}

return result
}

5. 其他厂商刘海屏适配

像华为、Oppo和Vivo这样的厂商,实现刘海屏的方式,也并不是按照 Android P的标准做的,它完全是自己修改了刘海屏的实现方式。不过他们是会提供完备的适配文档,这就需要我们直接阅读他们提供的开发文档来进行适配。各个厂商的刘海屏适配参​
考如下:

厂商介绍
华为https://mini.eastday.com/bdmip/180411011257629.html
Oppohttps://open.oppomobile.com/wiki/doc#id=10159
Vivohttps://dev.vivo.com.cn/doc/document/info?id=103

5.1.华为

华为提供了刘海屏Api,可以通过反射的方式调用。

5.1.1. 判断是否刘海屏接口

代码如下:

/**

  • 判断是否是华为刘海屏
  • @param context 上下文对象
  • @return true:是刘海屏;false:非刘海屏
    */
    fun hasNotchInScreen(context: Context): Boolean {
    var ret = false
    try {
    val cl = context.getClassLoader()
    val HwNotchSizeUtil = cl.loadClass(“com.huawei.android.util.HwNotchSizeUtil”)
    val method = HwNotchSizeUtil.getMethod(“hasNotchInScreen”)
    ret = method.invoke(HwNotchSizeUtil) as Boolean

} catch (e: ClassNotFoundException) {
Log.e(TAG, “hasNotchInScreen ClassNotFoundException”)
} catch (e: NoSuchMethodException) {
Log.e(TAG, “hasNotchInScreen NoSuchMethodException”)
} catch (e: Exception) {
Log.e(TAG, “hasNotchInScreen Exception”)
} finally {
return ret
}
}

5.1.2. 获取刘海尺寸信息接口

代码如下:

/**

  • 获取华为刘海的高宽
  • @param context 上下文对象
  • @return [0]值为刘海宽度int;[1]值为刘海高度
    */
    fun getNotchSize(context: Context): IntArray {
    var ret = intArrayOf(0, 0)
    try {
    val cl = context.classLoader
    val HwNotchSizeUtil = cl.loadClass(“com.huawei.android.util.HwNotchSizeUtil”)
    val method = HwNotchSizeUtil.getMethod(“getNotchSize”)
    ret = method.invoke(HwNotchSizeUtil) as IntArray
    } catch (e: ClassNotFoundException) {
    Log.e(TAG, “getNotchSize ClassNotFoundException”)
    } catch (e: NoSuchMethodException) {
    Log.e(TAG, “getNotchSize NoSuchMethodException”)
    } catch (e: Exception) {
    Log.e(TAG, “getNotchSize Exception”)
    } finally {
    return ret
    }
    }

5.1.3. 应用页面设置使用刘海区显示

给window添加华为新增的FLAG_NOTCH_SUPPORT方式,代码如下所示:

/**

  • 设置应用窗口在华为刘海屏手机使用挖孔区
  • @param window 应用页面window对象
    */
    fun setFullScreenWindowLayoutInDisplayCutout(window: Window?) {

if (null == window) {
return
}

val layoutParams: WindowManager.LayoutParams = window.attributes

try {
val layoutParamsExCls = Class.forName(“com.huawei.android.view.LayoutParamsEx”)
val con = layoutParamsExCls.getConstructor(WindowManager.LayoutParams::class.java)
val layoutParamsExObj = con.newInstance(layoutParams)
val method = layoutParamsExCls.getMethod(“addHwFlags”, Int::class.javaPrimitiveType)
method.invoke(layoutParamsExObj, FLAG_NOTCH_SUPPORT)
} catch (e: ClassNotFoundException) {
Log.e(TAG, “hw notch screen flag api error”)
} catch (e: NoSuchMethodException) {
Log.e(TAG, “hw notch screen flag api error”)
} catch (e: IllegalAccessException) {
Log.e(TAG, “hw notch screen flag api error”)
} catch (e: InstantiationException) {
Log.e(TAG, “hw notch screen flag api error”)
} catch (e: InvocationTargetException) {
Log.e(TAG, “hw notch screen flag api error”)
} catch (e: Exception) {
Log.e(TAG, “other Exception”)
}
}

5.2.Oppo

对于Oppo而言,它刘海的高度是固定的,就是80px。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

判断当前设备是否是刘海屏,也提供了对应的 Api,可以用以下方法获取。代码如下所示:

/**

  • 判断是否是Oppo刘海屏
  • @param context 上下文对象
  • @return true:是刘海屏;false:非刘海屏
    */
    fun hasNotchInScreenAtOppo(context: Context): Boolean {
    return context.packageManager!!.hasSystemFeature(“com.oppo.feature.screen.heteromorphism”)
    }

返回 true 为刘海屏,但是这种方法只能识别Oppo品牌所支持的刘海屏。

5.3.Vivo

在Vivo系统中,增加了一个接口来判断此设备是否具有凹槽,我们可以使用发射的方式调用。代码如下所示:

/**

  • 判断Voio是否有凹槽
  • @param context 上下文对象
  • @return true表示具备此特征,false表示没有此特征
    */
    fun hasNotchInScreenAtVoio(context: Context): Boolean {
    var ret = false
    try {
    val cl = context.classLoader
    val FtFeature = cl.loadClass(“android.util.FtFeature”)
    val method = FtFeature.getMethod(“isFeatureSupport”, Int::class.javaPrimitiveType)
    ret = method.invoke(FtFeature, NOTCH_IN_SCREEN_VOIO) as Boolean
    } catch (e: ClassNotFoundException) {
    Log.e(TAG, “hasNotchInScreen ClassNotFoundException”)
    } catch (e: NoSuchMethodException) {
    Log.e(TAG, “hasNotchInScreen NoSuchMethodException”)
    } catch (e: Exception) {
    Log.e(TAG, “hasNotchInScreen Exception”)
    } finally {
    return ret
    }
    }
    6. 结语
    ======
    看完本篇文章,我想你对Android P的刘海屏也有一定的认识了,现在还不确定不同厂商会不会对其微调,所以你要是碰到什么问题,欢迎一起研究学习,不妨在留言区留言讨论。

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取
,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助**。

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-NB6F1YCJ-1719099768272)]一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

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

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

相关文章

基于Vue-cli脚手架搭建项目使用ElementUI组件

项目结构 node_modules 项目依赖的外部组件文件放在此处,例如vue public index.html是对外提供的唯一的html文件 src assets 存放静态文件 例如图片 css js等文件 components 里面存放的是组件 App.vue是组件 main.js是项目配置文件 package.json存放的是项目依赖的…

1.树莓派4b+ubuntu18.04(ros版本melodic)+arduino mega自制两轮差速小车,实现建图导航功能

第一篇先介绍材料准备、环境配置和ros的安装 1.材料准备 1.树莓派4b&#xff0c;8g版本 2.arduino mega 3.MG310编码电机*2 4.雷达ydlidar X3 5.Tb6612电机驱动板 6.12v电池 7.ubuntu18.04ros melodic版本 2.环境配置 树莓派安装ubuntu18.04版本 ubuntu18.04版本的镜像可以…

访问网站时IP被屏蔽是什么原因?

在互联网使用中&#xff0c;有时我们可能会遇到访问某个网站时IP地址被屏蔽的情况。IP地址被网站屏蔽是一个相对常见的现象&#xff0c;而导致这种情况的原因多种多样&#xff0c;包括恶意行为、违规访问等。本文将解释IP地址被网站屏蔽的常见原因&#xff0c;同时&#xff0c;…

HarmonyOS-MPChart根据y轴刻度绘制渐变色曲线

本文是基于鸿蒙三方库mpchart&#xff08;OpenHarmony-SIG/ohos-MPChart&#xff09;的使用&#xff0c;自定义绘制方法&#xff0c;绘制一条颜色渐变的曲线。 mpchart本身的绘制功能是不支持颜色渐变的曲线的&#xff0c;只支持渐变色填充大块颜色。那么当我们的需求曲线根据…

【Linux】IP协议、以太网帧格式

目录 网络层IP协议协议头格式网段划分分类划分法特殊的 IP 地址IP 地址的数量限制私有 IP 地址和公有 IP 地址路由路由表生成算法 数据链路层以太网以太网帧格式认识 MAC 地址ARP协议ARP数据报格式 ARP 协议的工作流程ARP欺骗 DNShosts 文件域名的层级关系域名服务器分类域名解…

【计算机网络篇】数据链路层(12)交换机式以太网___以太网交换机

文章目录 &#x1f354;交换式以太网&#x1f6f8;以太网交换机 &#x1f354;交换式以太网 仅使用交换机&#xff08;不使用集线器&#xff09;的以太网就是交换式以太网 &#x1f6f8;以太网交换机 以太网交换机本质上就是一个多接口的网桥&#xff1a; 交换机的每个接口…

记MySQL事务+消息队列引起的问题

问题描述&#xff1a; 先说一下流程&#xff1a;后端保存前端提交的图表信息&#xff0c;然后发送异步消息到消息队列&#xff0c;由下游服务去处理图表信息。 部署项目到服务器&#xff0c;验证项目功能的时候&#xff0c;出现了以下错误&#xff1a;数据库存在数据。下游服…

计算机组成原理 —— 存储系统(DRAM和SRAM,ROM)

计算机组成原理 —— 存储系统&#xff08;DRAM和SRAM&#xff09; DRAM和SRAMDRAM的刷新DRAM地址复用ROM&#xff08;Read-Only Memory&#xff08;只读存储器&#xff09;&#xff09; 我们今天来看DRAM和SRAM&#xff1a; DRAM和SRAM DRAM&#xff08;动态随机存取存储器&…

构建未来应用的核心,云原生技术栈解析

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《未来已来&#xff1a;云原生之旅》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、云原生技术栈 1、容器和容器编排 1.1 Docker 1.2 Kubernete…

JaveEE进阶----Spring Web MVC入门

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、什么是 Spring Web MVC&#xff1f;&#xff1f;1.1MVC 定义1.2 什么是Spring MVC ?1.3过浏览器和用户程序交互 二、 RequestMapping 注解三、Postman 前言…

能理解你的意图的自动化采集工具——AI和爬虫相结合

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三连支…

计网:网络应用层【Email应用/SMTP协议】

Email应用与SMTP协议 Email应用层的构成 客户端服务器协议 用户代理 用于读写邮件消息&#xff1b;与服务器交互&#xff0c;收发邮件消息 常见的客户端&#xff1a;Outlook&#xff0c;Foxmail&#xff08;这两个是需要下载的客户端&#xff09;&#xff0c;Web客户端&…

浏览器插件利器-allWebPluginV2.0.0.14-bata版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX插件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持谷歌、火狐等浏…

【数据建模】微分方程与动力系统

文章目录 微分方程与动力系统1. 微分方程的理论基础1.1 函数、导数与微分1.2 一阶线性微分方程的解1.3 二阶常系数线性微分方程的解 2. 使用python求解微分方程2.1 求解微分2.2 求解定积分2.2.1 quad函数求解2.2.2 梯型法则求解 3. 使用Scipy和Sympy解微分方程3.1 使用sympy求解…

4. DSL入门_01

1. 常见的DSL (1) 查询所有: 查询出所有数据&#xff0c;一般测试的时候使用&#xff0c;例如&#xff1a; match_all .但是受分页限制&#xff0c;一般返回10条数据 (2) 全文检索(full text)查询&#xff1a;利用分词器对用户输入内容分词&#xff0c;然后去倒排索引中匹配&a…

三个 insert 导致的死锁问题

锁种类 插入意向锁&#xff08;insert intention lock&#xff09;对已有数据行的修改与删除&#xff0c;必须加强互斥锁 X 锁&#xff0c;那对于数据的插入&#xff0c;是否还需要加这么强的锁&#xff0c;来实施互斥呢&#xff1f;插入意向锁&#xff0c;孕育而生。插入意向…

任务5.2 掌握DStream基础操作

实战&#xff1a;DStream基础操作 了解DStream编程模型&#xff1a;DStream是Spark Streaming中对实时数据流的抽象&#xff0c;可以看作一系列持续的RDD。DStream可以通过外部数据源获取或通过现有DStream的高级操作获得。 操作本质&#xff1a;DStream上的操作最终会转化为对…

OneNote for Windows 10 下载

OneNote for Windows 10 安装 1.在浏览器中输入地址&#xff1a;https://apps.microsoft.com/detail/9wzdncrfhvjl?hlzh-cn&glUS2OneNote for Windows 10 - 在 Windows 上免费下载并安装 |Microsoft StoreOneNote 是用于在设备上捕获和组织你的一切内容的数字笔记本。快速…

对日期的处理

对日期的处理 对编码进行统一&#xff0c;在脚本最开始&#xff1a; # -*- coding: utf-8 -*-这里涉及到两个操作&#xff0c;一个是将数据进行标准化&#xff0c;比如有些日期是2024/05/06这并不符合日期的标准格式&#xff0c;需要转换成这样的2024-05-06 def tran_std(st…

八爪鱼现金流-030,升级日志

八爪鱼现金流 八爪鱼 2024年4月4日09:27:02 v-0.0.1 资产包、负债包&#xff0c;功能优化 2024年4月15日09:27:26 v-0.0.2 增加公告模块 2024年4月18日12:14:32 v-0.0.3 市场查询优化。创建人脱敏处理。增加市场风云菜单。 2024年4月18日15:57:10 v-0.0.4 对于无截止日…