虚拟键盘,即导航栏,如位置见下图。
fitsSystemWindows的使用
-
通过布局设置
fitsSystemWindows,使内容区预留 -
fitsSystemWindows生效前提:当前页面没有标题栏,并且状态栏或者底部导航栏透明fitsSystemWindows = true,表示内容区不延伸到状态栏或底部导航栏fitsSystemWindows = false,表示内容区延伸到状态栏或底部导航栏- 详情见链接
设置虚拟键盘颜色
window.clearFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
)
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.navigationBarColor = Color.BLACK
隐藏状态栏
val uiOptions =
View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE;
window.decorView.systemUiVisibility = uiOptions;
//适配刘海屏
if (android.os.Build.VERSION.SDK_INT >= 28) {
val lp = window.attributes
lp.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
window.attributes = lp
}
拓展工具
WindowInsetsControllerCompat最新 API推荐使用
- 开启导航栏
ViewCompat.getWindowInsetsController(findViewById<FrameLayout>(android.R.id.content))?.let { controller ->
controller.show(WindowInsetsCompat.Type.navigationBars())
controller.isAppearanceLightNavigationBars = true//true icon黑色,false白色
}
- 关闭导航栏
ViewCompat.getWindowInsetsController(findViewById<FrameLayout>(android.R.id.content))?.let { controller ->
controller.hide(WindowInsetsCompat.Type.navigationBars())
controller.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
- 是否显示导航栏
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
}
- 获取导航栏高度
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
}
异常情况
- 弹出
Dialog,导致Activity失去焦点,导航栏会再次出现
/**
* @author Vincent
* @date 2022/8/4
* @description
*
*/
class LoadingDialog(context: Context):Dialog(context, R.style.WaitDialogStyle) {
override fun create() {
super.create()
setContentView(R.layout.dialog_loading)
}
override fun show() {
window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
super.show()
val uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_FULLSCREEN
window?.decorView?.systemUiVisibility = uiOptions
window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
}
}
补充
状态栏隐藏,提供了三种行为模式,分别是如下:
WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH
滑动内容区域会显示导航栏,导航栏背景默认黑色
WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE
刷新导航栏区域,会出现导航栏,导航栏背景默认黑色
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
从屏幕边缘滑动,会出现导航栏,导航栏背景有一定的透明度,类似半透明状态,且显示短暂一会会自动消失
如果上面的自动隐藏不符合需求,需要在滑动后规定时间才隐藏导航栏的话,那么有什么方法可以监听导航栏呢?我们可以尝试监听页面系统状态可见性更改,比如导航栏隐藏会显示。然后在显示的情况下,开启定时任务,即可在规定时间隐藏导航栏,代码如下:
override fun onCreate(savedInstanceState: Bundle?) {
...
window.decorView.setOnApplyWindowInsetsListener { v, insets ->
hideNavigationBars()
insets
}
...
}
/**
* 关闭导航栏
*/
open fun hideNavigationBars(){
if(ViewCompat.getRootWindowInsets(findViewById<FrameLayout>(android.R.id.content))?.isVisible(WindowInsetsCompat.Type.navigationBars()) == true){
mBinding.root.postDelayed({
WindowCompat.getInsetsController(window,findViewById<FrameLayout>(android.R.id.content)).let { controller ->
controller.hide(WindowInsetsCompat.Type.navigationBars())
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE
}
},3000)
}
}