Kotlin实现全屏显示效果,挖空和刘海屏适配

为了实现全屏效果,不是黑边就是状态栏和内容视图重叠,这个真的头大,网上好不容易找到一篇文章,解决就是挖孔屏和刘海屏还是不同的实现方案,我真的要笑,没办法,学习吧

测试机:

Android 11 的 Xiaomi MI MAX 3

Android 12 的 Xiaomi K40 Pro

1. 该方法在api30后提示已经过时 在onCreat()方法中,setContentView()前使用。
Kotlin 复制代码
window.setFlags(
    WindowManager.LayoutParams.FLAG_FULLSCREEN,
    WindowManager.LayoutParams.FLAG_FULLSCREEN
)

测试结果:Android11和Android12均有效,但Android12的挖孔屏区域无效

2. 沉浸模式,查询到:Android系统到了4.4以后才提供沉浸式体验的支持。当设置透明效果后,4.4以下无效果,4.4~5.0全透明,5.0以上半透明;Android沉浸式模式的本质就是全屏化。
Kotlin 复制代码
	//该方法是从官网复制过来的,效果不如意
    private fun hideSystemBars() {
        val windowInsetsController =
            ViewCompat.getWindowInsetsController(window.decorView) ?: return
        // Configure the behavior of the hidden system bars
        windowInsetsController.systemBarsBehavior =
            WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        // Hide both the status bar and the navigation bar
        windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
    }

测试结果:Android11无效,Android12有效,Android12的挖孔屏区域无效。Android11获取windowInsetsController为null

Kotlin 复制代码
	//这是从别人那里拷过来的(csdn):https://blog.csdn.net/qq_32664007/article/details/126279919
    private fun hideSystemBars(window: Window) {
        //隐藏状态栏和导航栏 以及交互
        WindowInsetsControllerCompat(window, window.decorView).let {
            //隐藏状态栏和导航栏
            it.hide(WindowInsetsCompat.Type.systemBars())
            //交互效果
            it.systemBarsBehavior =
                WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        }
    }

测试结果:Android11无效,Android12有效,Android12的挖孔屏区域无效。

3.该方法在ide里提示已过时,在官网上未提示
Kotlin 复制代码
val decorView = window.decorView
decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
        or View.SYSTEM_UI_FLAG_FULLSCREEN
        or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)

测试结果:Android11和Android12均有效,但Android12的挖孔屏区域无效

4.该方法对测试机均有部分效过
Kotlin 复制代码
WindowCompat.setDecorFitsSystemWindows(window, false)

测试结果:Android11和Android12的activity绘制区域均将状态栏的区域绘制成功,但状态栏依然透明显示,Android12的挖孔屏区域无效,效果如图(按钮绘制在状态栏的位置上):

5.使用主题
Kotlin 复制代码
<item name="android:windowFullscreen">true</item>

测试结果:Android11有效,Android12有效,Android12的挖孔屏区域无效。

6.挖孔屏处理方式
Kotlin 复制代码
//允许window 的内容可以上移到刘海屏状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    val lp = window.attributes
    lp.layoutInDisplayCutoutMode =
        WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
    window.attributes = lp
}

测试结果:Android12 挖孔屏有效

封装成工具类:

Kotlin 复制代码
/**
 * 沉浸模式(全屏模式)
 * 设置全屏的方法
 * 参数window在activity或AppCompatActivity都带有
 */
fun immersionFull(window: Window) {
    hideSystemBars(window)
    useSpecialScreen(window)
}
Kotlin 复制代码
/**
 * 隐藏状态栏,显示内容上移到状态栏
 */
private fun hideSystemBars(window: Window) {
    //占满全屏,activity绘制将状态栏也加入绘制范围。
    //如此即使使用BEHAVIOR_SHOW_BARS_BY_SWIPE或BEHAVIOR_SHOW_BARS_BY_TOUCH
    //也不会因为状态栏的显示而导致activity的绘制区域出现变形
    //使用刘海屏也需要这一句进行全屏处理
    WindowCompat.setDecorFitsSystemWindows(window, false)
    //隐藏状态栏和导航栏 以及交互
    WindowInsetsControllerCompat(window, window.decorView).let {
        //隐藏状态栏和导航栏
        //用于WindowInsetsCompat.Type.systemBars()隐藏两个系统栏
        //用于WindowInsetsCompat.Type.statusBars()仅隐藏状态栏
        //用于WindowInsetsCompat.Type.navigationBars()仅隐藏导航栏
        it.hide(WindowInsetsCompat.Type.systemBars())
        //交互效果
        //BEHAVIOR_SHOW_BARS_BY_SWIPE 下拉状态栏操作可能会导致activity画面变形
        //BEHAVIOR_SHOW_BARS_BY_TOUCH 未测试到与BEHAVIOR_SHOW_BARS_BY_SWIPE的明显差异
        //BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE 下拉或上拉的屏幕交互操作会显示状态栏和导航栏
        it.systemBarsBehavior =
            WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    }
}
Kotlin 复制代码
/**
 * 扩展使用刘海屏
 */
private fun useSpecialScreen(window: Window) {
    //允许window 的内容可以上移到刘海屏状态栏
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        val lp = window.attributes
        lp.layoutInDisplayCutoutMode =
            WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
        window.attributes = lp
    }
}

然后资源目录的主题文件里添加(res->values->themes.xml):

Kotlin 复制代码
<!-- 导航栏透明 -->
<item name="android:navigationBarColor">
    @android:color/transparent
</item>
<!-- 状态栏透明 -->
<item name="android:statusBarColor">
    @android:color/transparent
</item>
<!-- 不要标题栏 -->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>

最后的效果就是:

对于手机底部区域全屏:

Kotlin 复制代码
<item name="android:windowTranslucentNavigation">true</item>
相关推荐
寻星探路2 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
工程师老罗4 小时前
如何在Android工程中配置NDK版本
android
lly2024064 小时前
Bootstrap 警告框
开发语言
2601_949146535 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧5 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
KYGALYX5 小时前
服务异步通信
开发语言·后端·微服务·ruby
zmzb01035 小时前
C++课后习题训练记录Day98
开发语言·c++
猫头虎6 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
YUJIANYUE6 小时前
PHP纹路验证码
开发语言·php
仟濹6 小时前
【Java基础】多态 | 打卡day2
java·开发语言