irpas技术客

WindowInsetsControllerCompat使用,新方式实现状态栏、导航栏、键盘控制_shetj

irpas 6168

WindowInsetsControllerCompat使用

文章目录 WindowInsetsControllerCompat使用添加依赖一、状态栏、导航栏相关1. 沉浸式设置2. 全屏3. 退出全屏4. 其他1. 显示状态栏,字体黑色2. 关闭状态栏3. 显示导航栏4. 隐藏导航栏5. 判断是否显示导航栏6. 获取导航栏的高度7. 获取状态栏的高度 二、键盘操作1. 显示和隐藏键盘2. 存在的问题3. 监听键盘高度变化更新-2022年4月1日

添加依赖

从core-ktx的1.5.0版本开始就是可以使用这个了。 首先添加依赖

implementation "androidx.core:core-ktx:1.7.0"

大概有以下类型

WindowInsetsCompat.Type.statusBars() WindowInsetsCompat.Type.navigationBars() WindowInsetsCompat.Type.captionBar() WindowInsetsCompat.Type.ime() WindowInsetsCompat.Type.systemGestures() WindowInsetsCompat.Type.mandatorySystemGestures() WindowInsetsCompat.Type.tappableElement() WindowInsetsCompat.Type.displayCutout() WindowInsetsCompat.Type.systemBars()

这里讲到的是:

WindowInsetsCompat.Type.ime() //键盘 WindowInsetsCompat.Type.statusBars() //状态栏 WindowInsetsCompat.Type.navigationBars() //导航栏 WindowInsetsCompat.Type.systemBars() //状态栏、导航栏和标题栏 一、状态栏、导航栏相关 1. 沉浸式设置 WindowCompat.setDecorFitsSystemWindows(window, false)

第二参数decorFitsSystemWindows表示是否沉浸,false 表示沉浸,true表示不沉浸

示例,沉浸入状态栏,状态栏字体黑色、底色透明:

//关键代码,沉浸 WindowCompat.setDecorFitsSystemWindows(window, false) //设置专栏栏和导航栏的底色,透明 window.statusBarColor = Color.TRANSPARENT window.navigationBarColor = Color.TRANSPARENT if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { window.navigationBarDividerColor = Color.TRANSPARENT } //设置沉浸后专栏栏和导航字体的颜色, ViewCompat.getWindowInsetsController(findViewById<FrameLayout>(android.R.id.content))?.let { controller -> controller.isAppearanceLightStatusBars = isBlack controller.isAppearanceLightNavigationBars = isBlack } 2. 全屏

WindowInsetsCompat.Type.systemBars()表示状态栏、导航栏和标题栏

fun Activity.hideSystemUI() { WindowCompat.setDecorFitsSystemWindows(window, false) ViewCompat.getWindowInsetsController(window.decorView)?.let { controller -> controller.hide(WindowInsetsCompat.Type.systemBars()) controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } } 3. 退出全屏 fun Activity.showSystemUI() { WindowCompat.setDecorFitsSystemWindows(window, true) ViewCompat.getWindowInsetsController(findViewById<FrameLayout>(android.R.id.content))?.show(WindowInsetsCompat.Type.systemBars()) } 4. 其他

状态栏和标题栏都是可以单独控制的。

1. 显示状态栏,字体黑色 window.statusBarColor = Color.TRANSPARENT //设置底色 ViewCompat.getWindowInsetsController(findViewById<FrameLayout>(android.R.id.content))?.let { controller -> controller.show(WindowInsetsCompat.Type.statusBars()) controller.isAppearanceLightStatusBars = true//true字体黑色,false白色 } 2. 关闭状态栏 ViewCompat.getWindowInsetsController(activity.findViewById<FrameLayout>(android.R.id.content))?.hide(WindowInsetsCompat.Type.statusBars()) 3. 显示导航栏 ViewCompat.getWindowInsetsController(findViewById<FrameLayout>(android.R.id.content))?.let { controller -> controller.show(WindowInsetsCompat.Type.navigationBars()) controller.isAppearanceLightNavigationBars = true//true icon黑色,false白色 } 4. 隐藏导航栏 fun FragmentActivity.hideNavigationBars() { ViewCompat.getWindowInsetsController(findViewById<FrameLayout>(android.R.id.content))?.let { controller -> controller.hide(Type.navigationBars()) controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } } 5. 判断是否显示导航栏 val FragmentActivity.windowInsetsCompat: WindowInsetsCompat? get() = ViewCompat.getRootWindowInsets(findViewById<FrameLayout>(android.R.id.content)) fun FragmentActivity.hasNavigationBars(): Boolean { val windowInsetsCompat = windowInsetsCompat ?: return false return windowInsetsCompat.isVisible(Type.navigationBars()) && windowInsetsCompat.getInsets(Type.navigationBars()).bottom > 0 } 6. 获取导航栏的高度 val FragmentActivity.windowInsetsCompat: WindowInsetsCompat? get() = ViewCompat.getRootWindowInsets(findViewById<FrameLayout>(android.R.id.content)) fun FragmentActivity.getNavigationBarsHeight(): Int { val windowInsetsCompat = windowInsetsCompat ?: return 0 return windowInsetsCompat.getInsets(Type.navigationBars()).bottom } 7. 获取状态栏的高度 val FragmentActivity.windowInsetsCompat: WindowInsetsCompat? get() = ViewCompat.getRootWindowInsets(findViewById<FrameLayout>(android.R.id.content)) fun FragmentActivity.getStatusBarsHeight(): Int { val windowInsetsCompat = windowInsetsCompat ?: return 0 return windowInsetsCompat.getInsets(Type.statusBars()).top } 二、键盘操作 1. 显示和隐藏键盘 @JvmStatic fun hideSoftKeyboard(activity: Activity) { ViewCompat.getWindowInsetsController(activity.findViewById<FrameLayout>(android.R.id.content)) ?.hide(WindowInsetsCompat.Type.ime()) } @JvmStatic fun showSoftKeyboard(activity: Activity) { ViewCompat.getWindowInsetsController(activity.findViewById<FrameLayout>(android.R.id.content)) ?.show(WindowInsetsCompat.Type.ime()) } 2. 存在的问题

只在dialog、fragment好像好像调用上面的打开键盘的方法没有效果,也有可能是我用错了。

所以当需要配合EditText打开的时候还是用老的方法

@JvmStatic fun focusEditShowKeyBoard(editText: EditText) { editText.isEnabled = true editText.isFocusable = true editText.isFocusableInTouchMode = true editText.requestFocus() val inputManager = editText.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager editText.setSelection(editText.text.length) inputManager.showSoftInput(editText, 0) } 3. 监听键盘高度变化 fun addKeyBordHeightChangeCallBack(view: View, onAction:(height:Int) ->Unit){ var posBottom: Int if (VERSION.SDK_INT >= VERSION_CODES.R) { val cb = object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) { override fun onProgress( insets: WindowInsets, animations: MutableList<WindowInsetsAnimation> ): WindowInsets { posBottom = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom + insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom onAction.invoke(posBottom) return insets } } view.setWindowInsetsAnimationCallback(cb) } else { ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -> posBottom = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom + insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom onAction.invoke(posBottom) insets } } }

使用:

var posBottom = 0 var maxBottom = 0 addKeyBordHeightChangeCallBack(mViewBinding.root) { posBottom = it maxBottom = max(maxBottom,posBottom) mViewBinding.guideline2.updateLayoutParams<ConstraintLayout.LayoutParams> { guidePercent = 1 - posBottom.toFloat() / screenHeight } mViewBinding.guideline.updateLayoutParams<ConstraintLayout.LayoutParams> { guidePercent =lastPercent - ((lastPercent-0.5f) * (posBottom.toFloat() / maxBottom) } }

更新-2022年4月1日 为了兼容低版本获取到WindowInsetsControllerCompat 需要: ViewCompat.getWindowInsetsController(window.decorView) 变更成 ViewCompat.getWindowInsetsController(findViewById<FrameLayout>(android.R.id.content))新增获取状态栏的高度和导航栏高度,判断是否有导航栏


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #新方式实现状态栏导航栏键盘控制 #首先添加依赖 #implementation