WindowInsetsControllerCompat学习

3,058 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

概述

在进行Android开发的过程中,我们很多时候都需要和系统相关的View打交道,比如状态栏,底部导航栏等。今天忽然发现了WindowCompat相关的类可以帮助我们直接处理相关的操作,不再需要我们像之前一样要根据不同的安卓版本去判断应该执行哪些操作,下面对这个类的相关使用做一个总结。

设置沉浸式

有时候我们需要将页面的布局显示到状态栏的下面,我们可以使用WindowCompat.setDecorFitsSystemWindows()方法轻松做到这一点,如下面的代码所示:

    WindowCompat.setDecorFitsSystemWindows(requireActivity().window,false)

上面是我们在Fragment中设置的沉浸式的方法,这个方法接收两个参数,一个是Window类型的,另一个是是否开启沉浸式,false标识开启沉浸式,true标识不开启沉浸式。使用上面的方法最终的效果如下:

开启沉浸式

从上面的图片可以看出,我们的内容布局设置到了状态栏的下面,虽然这里有标题栏看起来不太美观,但是加入我们的页面上部是一张图片等,设置到状态栏下面则会比较美观。

需要注意的是:当我们使用这种方式设置沉浸式的时候,我们不应该再使用fitSystemWindow属性,这个属性会导致这种方式失效。

设置状态栏的颜色

除了沉浸式,有时候为了我们的应用能够看起来更加美观,我们希望状态栏能够和我们的内容的颜色更加协调,这个时候就需要设置状态栏的颜色,下面的代码将状态栏的颜色设置为红色:

        //设置状态栏颜色
        requireActivity().window.statusBarColor = Color.RED

由于我这里的代码是在Fragment中执行的,所以会首先调用requireActivity()方法,如果是在Activity中则可以直接获取Window对象,下面是将状态栏设置为红色的效果:

将状态栏设置为红色

设置状态栏文字颜色

将状态栏设置为红色之后我们仍然能够看清楚状态栏上的信息,但是如果将状态栏设置为白色,则彻底无法看清状态栏上的信息了,因为状态栏上的信息展示的也是白色的。这种时候我们就需要调整状态栏上信息的颜色,我们可以将状态栏上的文字颜色调整为亮色或者暗色来让用户能够在设置了状态栏颜色之后仍然能够看得清相关的信息:

//将状态栏的前景色更改为浅色,相关的文字将会以深色呈现
val windowController = WindowCompat.getInsetsController(requireActivity().window,mBinding.root)
windowController.isAppearanceLightStatusBars = true

将状态栏的前景色设置为浅色

上面的图片就是将状态栏前景色设置为浅色的效果,如果我们期望文字显示为浅色,那么只需要将前景色设置为深色即可,也就是isAppearanceLightStatusBars传递为false即可。

设置导航栏颜色

有些手机还有虚拟导航栏,为了能够使得我们的应用能够更好地和导航栏相匹配,我们可能还需要设置导航栏的颜色,下面的代码设置了导航栏的颜色:

        requireActivity().window.navigationBarColor = Color.GREEN

这里将导航栏的颜色设置为绿色,下面是设置之后的效果:

设置导航栏颜色

可以看到导航栏的颜色已经变为绿色。

设置导航栏前景色

和设置状态栏的时候一样,对于导航栏,我们也可以调整它的前景色,通过调整前景色,可以改变导航栏上按钮的颜色,这样可以导航栏能够更好地和我们的应用相匹配,下面代码调整导航栏前景色为浅色:

        val windowController = WindowCompat.getInsetsController(requireActivity().window,mBinding.root)
        windowController.isAppearanceLightNavigationBars = true

设置导航栏前景色为浅色

设置导航栏透明色

有时候我们页面的内容可能是图片等,这时候我们可能需要图片能够显示到导航栏的下面,尽可能利用屏幕的空间。想要实现这个效果,我们只需要将导航栏的颜色设置为透明即可让我们的页面内容显示到导航栏的下面,如下所示:

        //设置导航栏为透明色
        requireActivity().window.navigationBarColor = Color.TRANSPARENT

设置导航栏为透明色

需要注意的是:如果我们已经将导航栏设置为透明色,则不能再将导航栏前景色设置为浅色,否则透明色则无效。

控制系统View的显示和隐藏

很多时候我们不仅需要控制状态栏和导航栏的颜色,我们还需要控制它们的行为,比如在玩游戏或者看视频的时候我们希望导航栏和状态栏能够隐藏,这样相关的内容就不会被遮盖,使用WindowInsetsControllerCompat可以很容易帮我们做到这一点。

控制状态栏

        val windowController = WindowCompat.getInsetsController(requireActivity().window,mBinding.root)
        //隐藏状态栏
        mBinding.btnHideStatusBar.setOnClickListener {
            windowController.hide(WindowInsetsCompat.Type.statusBars())
        }

        //显示状态栏
        mBinding.btnShowStatusBar.setOnClickListener {
            windowController.show(WindowInsetsCompat.Type.statusBars())
        }

通过上面的两行代码我们就可以控制状态栏的显示和隐藏了,运行效果如下所示:

显示/隐藏状态栏

控制导航栏

和控制状态栏的代码一样,我们只需要给WindowInsetsControllerCompatshow()或者hide()方法传递导航栏的类型即可控制导航栏的显示和隐藏:

        val windowController = WindowCompat.getInsetsController(requireActivity().window,mBinding.root)
        //隐藏导航栏
        mBinding.btnHideNavigationBar.setOnClickListener {
            windowController.hide(WindowInsetsCompat.Type.navigationBars())
        }

        //显示导航栏
        mBinding.btnShowNavigationBar.setOnClickListener {
            windowController.show(WindowInsetsCompat.Type.navigationBars())
        }

显示/隐藏导航栏

控制键盘

除了状态栏和导航栏,还可以通知键盘的弹出和隐藏,如下面的代码所示:

        val windowController = WindowCompat.getInsetsController(requireActivity().window,mBinding.editText)
        //隐藏键盘
        mBinding.btnHideIme.setOnClickListener {
            windowController.hide(WindowInsetsCompat.Type.ime())
        }

        //显示键盘
        mBinding.btnShowIme.setOnClickListener {
            windowController.show(WindowInsetsCompat.Type.ime())
        }

上面的代码运行的效果如下:

显示/隐藏键盘

需要注意的是:为了能够控制键盘,我们的页面上必须有至少一个输入框,否则仅仅使用上面的方法是无法控制键盘的显示和隐藏的。有输入框的时候还不够,还需要在控制键盘的时候让输入框上焦,这一点可以通过两种方式实现:一种是直接调用输入框的requestFocus方法让输入框上焦,一种是获得WindowInsetsControllerCompat对象的时候将输入框View传递给WindowCompat.getInsetsController()的第二个参数。

其它系统View

上面介绍了WindowInsetsController可以帮助我们控制的三种常见的系统View,WindowInsetsCompat还提供了以下类型:

系统View类型说明
statusBars()状态栏
navigationBars()导航栏
captionBar()标题栏
ime()键盘
systemGestures()一个表示系统手势插入的类型
mandatorySystemGestures()一个表示强制性系统手势插图
systemBars()所有系统栏,标题栏,状态栏和导航栏