• Android开发 WindowInsetsController 窗口控制器


    前言

      在Android11后,google推出了WindowInsetsController 来取代之前复杂麻烦的窗口控制. 意在将Android的窗口控制更简单. 这里说明下什么是窗口控制,在Android手机里,状态栏,导航栏.输入法等等这些与app无关,但是需要配合app一起使用的窗口部件.

    另外注意WindowInsetsController需要Android 11 (R) API 30 才能使用, google提供了ViewCompat作为向下的兼容.

    添加依赖

        implementation 'androidx.core:core:1.6.0'

    隐藏or显示输入法

        private fun changeKeyboard(isShow: Boolean){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                if (isShow){
                    window?.insetsController?.show(WindowInsets.Type.ime())
                } else{
                    window?.insetsController?.hide(WindowInsets.Type.ime())
                }
            } else {
                ViewCompat.getWindowInsetsController(btn1).let { controller ->
                    if (isShow){
                        controller?.show(WindowInsetsCompat.Type.ime())
                    } else{
                        controller?.hide(WindowInsetsCompat.Type.ime())
                    }
                }
            }
        }

    监听输入法高度

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                window.setDecorFitsSystemWindows(false)//这个一定要添加
                root.setWindowInsetsAnimationCallback(object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
                    override fun onProgress(insets: WindowInsets, runningAnimations: MutableList<WindowInsetsAnimation>): WindowInsets {
                        val isVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
                        val keyboardHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
                        Log.e(TAG, "isVisible = $isVisible")
                        Log.e(TAG, "position = $keyboardHeight")
                        return insets
                    }
                })
            } else {
                /*
                 * 此兼容代码,并没有用,具体原因并不知道,但是上面的api30的代码还是正常的
                 */
                ViewCompat.setOnApplyWindowInsetsListener(root) { v, insets ->
                    val isVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
                    val keyboardHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
                    Log.e(TAG, "isVisible = $isVisible")
                    Log.e(TAG, "keyboardHeight = $keyboardHeight")
                    insets
                }
            }

    隐藏or显示状态栏

        private fun changeStatusBars(isShow: Boolean){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                if (isShow){
                    window?.insetsController?.show(WindowInsets.Type.statusBars())
                } else{
                    window?.insetsController?.hide(WindowInsets.Type.statusBars())
                }
            } else {
                ViewCompat.getWindowInsetsController(btn1).let { controller ->
                    if (isShow){
                        controller?.show(WindowInsetsCompat.Type.statusBars())
                    } else{
                        controller?.hide(WindowInsetsCompat.Type.statusBars())
                    }
                }
            }
        }

    让状态栏显示的操作方式

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                window?.insetsController?.hide(WindowInsets.Type.statusBars())
                /*
               * BEHAVIOR_SHOW_BARS_BY_TOUCH,  触摸显示状态栏 api31已经弃用
               * BEHAVIOR_SHOW_BARS_BY_SWIPE   滑动显示状态栏 api31已经弃用
               * BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE 通过滑动短暂显示半透明状态栏(一般情况下推荐这个)
               */
                window?.insetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
            }

    改变状态栏的文字颜色

    只有2种选择,暗色与高亮

        /**
         * 改变状态栏文字颜色
         * 只有2种选择,白色与黑色
         */
        private fun changeStatusFountColor(isLight: Boolean) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                //android R (android 11, API 30) 使用下面的新api
                /*
                 传入0则是清理状态,恢复高亮
                 */
                val state = if (isLight) WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS else 0
                window?.insetsController?.setSystemBarsAppearance(state, WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS)
            } else {
                //低于android R 使用兼容模式
                ViewCompat.getWindowInsetsController(btn1).let { controller ->
                    controller?.isAppearanceLightStatusBars = isLight
                }
            }
        }

    隐藏or显示导航栏

        private fun changeNavigationBars(isShow: Boolean) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                if (isShow){
                    window?.insetsController?.show(WindowInsets.Type.navigationBars())
                } else{
                    window?.insetsController?.hide(WindowInsets.Type.navigationBars())
                }
            } else {
                ViewCompat.getWindowInsetsController(btn1).let { controller ->
                    if (isShow){
                        controller?.show(WindowInsetsCompat.Type.navigationBars())
                    } else{
                        controller?.hide(WindowInsetsCompat.Type.navigationBars())
                    }
                }
            }
        }

    隐藏or显示系统栏(其实就是导航栏+状态栏)

    这种同时隐藏导航栏与状态栏的方式,时候在播放视频的时候使用

        private fun changeSystemStatus(isShow: Boolean) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                if (isShow){
                    window?.insetsController?.show(WindowInsets.Type.systemBars())
                } else{
                    window?.insetsController?.hide(WindowInsets.Type.systemBars())
                }
            } else {
                ViewCompat.getWindowInsetsController(btn1).let { controller ->
                    if (isShow){
                        controller?.show(WindowInsetsCompat.Type.systemBars())
                    } else{
                        controller?.hide(WindowInsetsCompat.Type.systemBars())
                    }
                }
            }
        }

    End

  • 相关阅读:
    【华为云技术分享】从自建MongoDB聊聊云数据库MongoDB的蓬勃张力
    【华为云技术分享】【Python算法】分类与预测——支持向量机
    Python 中更优雅的环境变量设置方案
    Python解析照片EXIF信息,获取坐标位置
    【华为云技术分享】【Python算法】分类与预测——决策树
    【华为云技术分享】使用keil5打开GD32F450i的MDK项目出现的问题以及J-Link无法烧录程序对应的解决方案
    【华为云技术分享】小熊派IoT开发板华为物联网操作系统LiteOS内核实战教程01-IoT-Studio介绍及安装
    【华为云技术分享】【开发记录】Linux服务器维护常用命令(二)
    【PHP输出两位小数】使用PHP来输出保留两位小数的数字【原创】
    【SERVER_NAME】PHP中的SERVER_NAME【原创】
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/15908639.html
Copyright © 2020-2023  润新知