Android核心技术深入浅出Android读书

隐藏系统导航栏

2021-07-26  本文已影响0人  安卓技术砖家

竖屏下导航栏一般不会去做隐藏处理,因为看起来不会别扭,使用也更方便,但是横屏的应用体验就没有那么好了,启用起来也别扭,特别是导航栏还能设置隐藏和显示这种操作,这操作会导致根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是透明的,但还是能接受。

上一篇下一篇

猜你喜欢

热点阅读