隐藏系统导航栏

作者: 安卓技术砖家 | 来源:发表于2021-07-22 00:03 被阅读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是透明的,但还是能接受。

    相关文章

      网友评论

        本文标题:隐藏系统导航栏

        本文链接:https://www.haomeiwen.com/subject/jzfjmltx.html