Android进阶之路Android技术知识Android开发经验谈

隐藏系统导航栏

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中也能操作。

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了

 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是透明的,但还是能接受。
好了 代码不多,多在上面,就不给源码地址了。

上一篇 下一篇

猜你喜欢

热点阅读