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

如下图所示:

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

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

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.mzph.cn/bicheng/32834.shtml

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

相关文章

使用VisualBox+Vagrant搭建Centos虚拟机环境

1.下载并安装VisualBox&#xff1b; 2.下载并安装Vagrant; 3.打开cmd窗口&#xff0c;执行命令vagrant init centos/7&#xff0c;初始化centos环境&#xff0c;该步骤受网络带宽影响&#xff0c;可能挂级30分钟到1个小时&#xff1b; 4.启动虚拟机&#xff1a;vagrant up&…

数据库理论大题与编译原理大题(笔记)

目录 数据库&#xff08;求最小函数依赖&#xff09; 数据库&#xff08;求属性集的闭包和候选码&#xff09; 编译原理&#xff08;NFA ——> DFA&#xff09; 编译原理&#xff08;识别文法的活前缀 DFA 和 LR(0) 分析表&#xff09; 哈哈&#xff01;这是本人作者才…

WordPress强大多功能主题模板The7 v9.16.0

模板介绍 The7可以与WPBakery Page Builder&#xff08;原Visual Composer&#xff09;和Ultimate Addons的完全无缝集成。它也与大多数流行的插件完全兼容&#xff0c;例如WooCommerce&#xff0c;WPML&#xff0c;Yoast SEO&#xff0c;All in One WP Migration&#xff0c;…

Windows系统下安装RabbitMQ详细步骤

声明&#xff1a;原文参考链接出自&#xff1a; 如何在Windows系统下安装RabbitMQ_rabbitmq windows安装-CSDN博客 https://zhuanlan.zhihu.com/p/693160757 一、RabbitMQ安装软件资源准备 因为RabbitMQ是Erlang语言开发的&#xff0c;因此安装Erlang环境在进行安装RbbitMQ的…

无需破解,打开就是旗舰版!

在当今快节奏的工作环境里&#xff0c;有效的视觉沟通变得至关重要。流程图、思维导图、组织结构图等图表能够帮助我们以清晰、直观的方式传达复杂信息。而Wondershare Edraw Max正是这样一款强大的绘图工具&#xff0c;它能够帮助用户轻松创建各种专业图表。 软件链接&#x…

基于springboot websocket和okhttp实现消息中转

1、业务介绍 消息源服务的消息不能直接推给用户侧&#xff0c;用户与中间服务建立websocket连接&#xff0c;中间服务再与源服务建立websocket连接&#xff0c;源服务的消息推给中间服务&#xff0c;中间服务再将消息推送给用户。流程如下图&#xff1a; 此例中我们定义中间服…

解析PDF文件中的图片为文本

解析PDF文件中的图片为文本 1 介绍 解析PDF文件中的图片&#xff0c;由两种思路&#xff0c;一种是自己读取PDF文件中的图片&#xff0c;然后用OCR解析&#xff0c;例如&#xff1a;使用PyMuPDF读取pdf文件&#xff0c;再用PaddleOCR或者Tesseract-OCR识别文字。另一种使用第…

信息学奥赛初赛天天练-32-CSP-J2022基础题-中缀表达式、后缀表达式、哈夫曼编码、连通图、邻居矩阵、完全二叉树、数组存储

PDF文档公众号回复关键字:20240623 2022 CSP-J 选择题 单项选择题&#xff08;共15题&#xff0c;每题2分&#xff0c;共计30分&#xff1a;每题有且仅有一个正确选项&#xff09; 6.对表达式a(b-c)*d的前缀表达式为( ),其中 、- 、 * 是运算符。 A. * a - bcd B. a * - …

【从0实现React18】 (四) 如何触发更新 带你了解react触发更新的流程以及更新后如何触发render

常见的触发更新的方式 创建 React 应用的根对象 ReactDOM.creatRoot().render()&#xff1b;类组件 this.setState()&#xff1b;函数组件 useState useEffect&#xff1b; 我们希望实现一套统一的更新机制&#xff0c;他的特点是&#xff1a; 兼容上述触发更新的方式方便后续…

c++学习-----内存管理

1. C/C内存分布 我们先来看下面的一段代码和相关问题 答案揭晓&#xff1a; 这里很多人会误认为*char2在常量区&#xff0c;这其实是错误的 因为&#xff1a; 首先在内存字符常量区分配一块内存空间放下”abcd\0”&#xff0c;然后在栈中分配一块连续的内存空间&#xff0c;…

SQL-Python

师从黑马程序员 数据库介绍 数据库就是存储数据的库 数据组织&#xff1a;库->表->数据 数据库和SQL的关系 MySQL的基础命令 SQL基础 SQL语言的分类 SQL的语法特征 DDL-库管理 show DATABASES;use sys;SELECT database();CREATE DATABASE test CHARSET utf-8;SHOW D…

学习C++第二天

1.缺省参数 缺省参数的概念&#xff1a; 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&#xff0c;如果没有指定实参则采用该形参的缺省值&#xff0c;否则使用指定的实参。 void show(int a 10) {cout << a << endl; }int main() {sho…

ubuntu18.04 编译HBA 并实例运行

HBA是一个激光点云层级式的全局优化的程序&#xff0c;他的论文题目是&#xff1a;HBA: A Globally Consistent and Efficient Large-Scale LiDAR Mapping Module&#xff0c;对应的github地址是&#xff1a;HKU-Mars-Lab GitHub 学习本博客&#xff0c;可以学到gtsam安装&am…

提升Python技能的七个函数式编程技巧

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 递归📝 结构化模式匹配📝 不变性📝 纯函数📝 高阶函数📝 函数组合📝 惰性求值⚓️ 相关链接 ⚓️📖 介绍 📖 在现代编程中,虽然Python并不是一门纯粹的函数式编程语言,但函数式编程(Funct…

Linux C/C++ socket函数

目录 socket函数 函数原型 头文件 功能 返回值 参数 错误码 socket函数 函数原型 int socket(int domain, int type, int protocol); 头文件 #include <sys/types.h> #include <sys/socket.h> 功能 创建一个用于通信的端点&#xff0c;并返回一个文件描述符…

登录安全分析报告:链家地产

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

力扣刷题 杨辉三角(使用c++ vector解法)

杨辉三角 题目描述示例1示例2提示:代码 题目描述 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例1 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例2 …

上位机图像处理和嵌入式模块部署(mcu和swd接口)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 最近学习mcu的时候&#xff0c;接触了不少调试器&#xff0c;这里面有daplink、st-link v2、j-link v9。虽然模块的形状可能不太一样&#xff0c;但…

基于I2C协议的AHT20温湿度传感器的数据采集

一、I2C总线通信协议 软件I2C 软件I2C&#xff0c;也称为模拟I2C或bit-bang I2C&#xff0c;是一种通过微控制器的通用输入输出&#xff08;GPIO&#xff09;引脚来模拟I2C总线通信的方式。它不依赖于专门的硬件I2C接口&#xff0c;而是通过编程控制GPIO引脚的电平状态来实现I…

快去复习吧+++常用算法及参考算法 递推法++穷举法++排序(冒泡、选择)++查找(顺序、折半)++字符串处理++方程求根++无穷级数求和

接上&#xff1a;常用算法及参考算法 &#xff08;1&#xff09;累加 &#xff08;2&#xff09;累乘 &#xff08;3&#xff09;素数 &#xff08;4&#xff09;最大公约数 &#xff08;5&#xff09;最值问题 &#xff08;6&#xff09;迭代法 常用算法及参考算法 7. 递推法…