隐藏系统导航栏
2018-08-31 本文已影响8人
暗影1
竖屏下导航栏一般不会去做隐藏处理,因为看起来不会别扭,使用也更方便,但是横屏的应用体验就没有那么好了,启用起来也别扭,特别是导航栏还能设置隐藏和显示这种操作,这操作会导致根View重绘。
一开始以为很简单的一个需求,但是实现起来还是遇到些问题,在次记录下。
Activity的话直接参考官方文档全屏显示页面。
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
hideNavigationBar()
}
}
protected fun hideNavigationBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
setSystemUiVisibly()
}
}
private fun setSystemUiVisibly() {
window.decorView.systemUiVisibility = (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_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_FULLSCREEN
// 沉浸式
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
)
}
一开始以为这样就完了,文档也是这么写的,但是当页面有Dialog,Popupwindow的时候就有问题了,问题是导航栏弹出来后就不会隐藏了,悲痛啊,还会挡住UI。
所以害的处理Dialog,PopupWindow。
因为systemUiVisibility方法是View里面的方法,所以在Dialog和PopupWindow中也能操作。
- Dialog
override fun show() {
this.window!!.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
super.show()
hideNavigationBar()
this.window!!.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
setSystemUiVisibly()
}
}
protected fun hideNavigationBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
setSystemUiVisibly()
}
}
private fun setSystemUiVisibly() {
window!!.decorView.systemUiVisibility = (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_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_FULLSCREEN
// 沉浸式
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
这样处理后就不会弹出系统UI了
- PopupWindow
override fun showAsDropDown(anchor: View?, xoff: Int, yoff: Int, gravity: Int) {
val tempFocusable = isFocusable
beforeShow()
super.showAsDropDown(anchor, xoff, yoff, gravity)
afterShow(tempFocusable)
}
override fun showAtLocation(parent: View?, gravity: Int, x: Int, y: Int) {
val tempFocusable = isFocusable
beforeShow()
super.showAtLocation(parent, gravity, x, y)
afterShow(tempFocusable)
}
private fun afterShow(tempFocusable: Boolean) {
hideNavigationBar(contentView)
isFocusable = tempFocusable
update()
}
private fun beforeShow() {
isFocusable = false
}
protected fun hideNavigationBar(view: View) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
setSystemUiVisibly(view)
}
}
private fun setSystemUiVisibly(view: View) {
view.systemUiVisibility = (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_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_FULLSCREEN
// 沉浸式
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
PopupWindow也是这样处理,注意焦点的处理。
这样就完了吗?
既然会这么问肯定还有坑啊,就是输入框,弹出输入框的时候也还是显示系统UI 关闭输入框后不会隐藏,会挡住我们自己的UI,惨啊,怎么办?
查看View代码后发现了这个方法setOnSystemUiVisibilityChangeListener
所以
window.decorView.setOnSystemUiVisibilityChangeListener {
if (it === View.SYSTEM_UI_FLAG_VISIBLE) {
hideNavigationBar()
}
}
只要显示就调用下隐藏方法,这样基本就解决了所有问题了,还有点瑕疵是这样会导致输入法弹出来的时候NavigationBar是透明的,但还是能接受。
好了 代码不多,多在上面,就不给源码地址了。