“我报名参与金石方案1期挑战——分割10万奖池,这是我的第1篇文章,点击检查活动详情”

前语

本文总结 Android 完成沉溺式全屏的完成办法。

完成沉溺式全屏

在一些需求全屏显现的场景下,比方玩游戏、看横屏视频的时候,内容全屏占满窗口的体会会让用户更加沉溺到对内容的消费中,带来更好的用户体会。

沉溺式显现具体来说便是如状态栏和导航栏部分的显现作用调整。当然,这儿关于不同的产品形状会有不同的选择。

状态栏文本、icon 的色彩、状态栏自身的背景色、导航栏的背景色以及是否显现,通过这些组合能够呈现出不同的用户体会。下面就从这两个组件的运用出发,看看怎么完成沉溺式的作用。

Android 实现沉浸式全屏的总结

Android 实现沉浸式全屏的总结


状态栏

状态栏背景色

关于状态栏,首先是状态栏背景色, 这个根据需求设置就好了,一般情况下设置为通明比较好适配。

window.statusBarColor = Color.TRANSPARENT

状态栏文字色彩

关于状态栏、导航栏的其他操作,咱们能够运用系统的 WindowInsetsControllerCompat 这个类,从姓名 Compat 就能够看到,这是一个兼容的类。关于沉溺式状态栏的完成,由于 Android 在国内变成了「安卓」,因而前期关于状态各种属性的适配能够说是群魔乱舞,各式各样的 StatusBarUtils 大行其道。现在好了,Android 官方终于统一天下,亲身下场来搞了,这下关于沉溺式的完成就比较简略了。

WindowInsetsControllerCompat 的运用也很简略,创建一个他的实例即可。

val controller = WindowInsetsControllerCompat(window, window.decorView)

后边的全部运用这个实例就能够了,API 很简略,命名一望而知。

比方更改状态色彩这个功用。关于状态栏文字的色彩,Android 官方只允许设置黑色或许白色

controller.isAppearanceLightStatusBars = true // 黑色状态栏
// or 
controller.isAppearanceLightStatusBars = false // 白色状态栏

留意、留意、留意 ,这儿的注释没有写错,这个办法便是这么奇怪,自己一开端运用也是被绕晕了。但便是这样。还有一点需求留意的是,Android 6.0 也便是 Android SDK 23 开端,才能够运用这个 feature 。

状态栏显现与躲藏

controller.hide(WindowInsetsCompat.Type.statusBars()) // 状态栏躲藏
// or
controller.show(WindowInsetsCompat.Type.statusBars()) // 状态栏显现

这个就很简略了。

导航栏

说完了状态栏,在来看导航栏。比较状态栏,导航栏上不会有文字,一般情况下便是一条底部的横线。因而,咱们只需求关怀导航的背景色和可见性即可。

导航栏背景色

window.navigationBarColor = Color.TRANSPARENT

导航栏横线的色彩

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    window.navigationBarDividerColor = Color.TRANSPARENT
}

从 Android P (28) 也便是 Android 9.0 开端,咱们乃至能够设置导航栏横线的色彩了。

潜在的坑

这儿再弥补一个最近遇到的关于设置状态栏和导航栏色彩的坑。假如当时 Activity 的 theme 属性中包含如下内容

    <style name="BugTheme" parent="AppTheme">
        <item name="android:windowTranslucentNavigation">true</item>
        <item name="android:windowTranslucentStatus">true</item>
    </style>

这儿的坑便是由这个 Translucent 导致的。Translucent 的意思是半通明,Transparent 的意思才是通明。这两个单词从拼写到发音都有些类似,理论上说二者的作用也是类似,无非便是通明度的值不一样而已。但便是这细微的不同,简单导致问题。一旦给 Activity 的 theme 设置了如上的了解,那么后续通过 window.statusBarColorwindow.navigationBarColor 设置色彩就不在生效了。

导航栏显现与躲藏

导航栏显现与躲藏的办法,和状态栏显现躲藏的办法十分类似,改变一下参数即可。

controller.hide(WindowInsetsCompat.Type.navigationBars()) // 导航栏躲藏
// or
controller.show(WindowInsetsCompat.Type.navigationBars()) // 导航栏显现

沉溺式

WindowCompat.setDecorFitsSystemWindows(window, false) // 打开沉溺式
// or
WindowCompat.setDecorFitsSystemWindows(window, true) // 封闭沉溺式
沉溺式开 沉溺式封闭
Android 实现沉浸式全屏的总结
Android 实现沉浸式全屏的总结

能够看到,运用 WindowInsetsControllerCompat ,沉溺式便是这么简略。

适配全面屏

从上面沉溺式的图,能够看到其实还是有点问题,便是横屏之后,屏幕左边并没有完全铺开,而是有一段黑边,看着十分难受了。这其实是关于异形屏的适配问题。

其实这段黑边便是刘海屏的区域,Android 官方叫做 DisplayCutout area 这个区域也是有专门的参数进行适配。

val params = window.attributes
params.layoutInDisplayCutoutMode =
                        WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
window.attributes = params

大于等于 Android 9.0 (SDK 28 P)的设备都支撑。关于 layoutInDisplayCutoutMode 参数有三种类型。

关于这三个参数,还要考虑当时屏幕是横屏还是竖屏。

LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT

这个是默许参数。

竖屏状态

假如没有设置全屏显现的属性,那么内容是延伸到 DisplayCutout area 的。这种情况下,假如进行全屏和非全屏的切换操作,会发现内容在整体上下跳动。比方在这种情况下,调用 controller.hide(WindowInsetsCompat.Type.statusBars()) 进行状态栏的显现躲藏的操作,就会发现整个内容在上下跳动,在上面的动图里很明显了。

横屏状态

横屏状态下,顶部的状态栏就变成左边或许右边(这儿看屏幕是怎么旋转的,可能是旋转了 -90 度,也可能是 270 度)的黑边了。内容不会延伸到左右两边的 DisplayCutout area 里。

LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES

这种情况下,内容是默许延伸到 DisplayCutout area 的。因而,全屏和非全屏操作的时候,就不会有内容上下跳动或许黑边的问题了。

LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER

这种情况,内容永久不会延伸到 DisplayCutout area 里面。

关于这个三个参数和沉溺式状态的设置,能够进行自由组合,会有不同的作用。具体要怎样,就看实践事务需求了。 比方 Android 官方的相册运用,当咱们点击一张图片进行预览的时候,顶部状态栏是全屏之后才慢慢躲藏的。

关于 LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 和 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 的差异,咱们用两张图比较一下就大概明白了。

LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
Android 实现沉浸式全屏的总结
Android 实现沉浸式全屏的总结

能够看到,LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 形式下,整个内容都撑开到刘海的区域了。屏占比更高了,看着也更舒服了。

需求留意的是,刘海屏适配还牵扯到屏幕内容高度(竖屏)或许内容宽度的核算问题。实践的分辨率、displayMetrics.widthPixelsdisplayMetrics.heightPixels 这些值是不变的。但是跟着刘海区域的改变,实践内容可展现的区域是有改变的,因而还需求做好适配相关的问题。

总结

运用官方提供的 WindowInsetsControllerCompat 的系列 API,操作状态栏及导航栏,以及沉溺式的完成相对来说比较简略了,底层处理了各个版别之间的兼容性。关于文中提到的相关类和办法的运用,更多细节能够检查参考文档中的链接。

参考

  • blog.csdn.net/StjunF/arti…
  • blog.csdn.net/jingzz1/art…
  • guolin.blog.csdn.net/article/det…
  • /post/690978…
  • www.jianshu.com/p/ab0344bda…