Android:如何在方向更改时保留沉浸式模式?

时间:2018-02-17 21:05:42

标签: android kotlin screen-orientation android-immersive

目前在活动类中使用此代码块进入粘性沉浸式模式:

override fun onWindowFocusChanged(hasFocus:Boolean) {
        super.onWindowFocusChanged(hasFocus)

        if (hasFocus && android.os.Build.VERSION.SDK_INT > 15)
        {
            var flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
                    View.SYSTEM_UI_FLAG_FULLSCREEN
            flags = if (android.os.Build.VERSION.SDK_INT < 19) flags else                           
                flags or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            window.decorView.systemUiVisibility = flags
        }
    }

切换方向时,状态栏会返回(甚至不是半透明)并保持拖动状态,然后再次消失。我真的不明白这种行为的原因,我该如何解决?

提前谢谢。

4 个答案:

答案 0 :(得分:1)

当我使用文档中的内容时,我遇到了类似的问题,仅使用onWindowFocusChanged我试图隐藏SystemUi。切换到横向模式时,它只能在纵向模式下使用。

在文档中,我还发现OnSystemUiVisibilityChangeListener,当系统ui可见时,它将获得回调。您可以检查SYSTEM_UI_FLAG_FULLSCREEN == 0并再次调用hideSystemUi()。

这在风景和肖像上都对我有用:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
window.decorView.setOnSystemUiVisibilityChangeListener { visibility ->
        // Note that system bars will only be "visible" if none of the
        // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
        if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
            hideSystemUI()
            // adjustments to your UI, such as showing the action bar or
            // other navigational controls.
        }
    }
}

override fun onWindowFocusChanged(hasFocus: Boolean) {
    super.onWindowFocusChanged(hasFocus)
    if (hasFocus) hideSystemUI()
}


private fun hideSystemUI() {
    window.decorView.systemUiVisibility = (
            // Set the content to appear under the system bars so that the
            // content doesn't resize when the system bars hide and show.
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    // Hide the nav bar and status bar
                    or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_FULLSCREEN)
}

答案 1 :(得分:0)

我认为隐藏工具栏的唯一方法

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    getSupportActionBar()?.hide()
    onWindowFocusChanged(true)
}


override fun onWindowFocusChanged(hasFocus: Boolean) {
    super.onWindowFocusChanged(hasFocus)

    if (hasFocus && android.os.Build.VERSION.SDK_INT > 15) {
        var flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
                View.SYSTEM_UI_FLAG_FULLSCREEN
        flags = if (android.os.Build.VERSION.SDK_INT < 19) flags else
            flags or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
        window.decorView.systemUiVisibility = flags
    }
}

答案 2 :(得分:0)

我刚刚尝试过,它看起来真的很好:

@Override
protected void onResume() {
    super.onResume();
    enableStickyImmersiveMode();
}

private void enableStickyImmersiveMode() {
    View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);
}

答案 3 :(得分:0)

我从 Android 9.0 (API-28) 开始就遇到过这种症状。

当我在初始化过程中观察到这些 System_UI_FLAG_* 标志并且 decorView 被设置为 OnSystemUiVisibilityChangeListener 时,底层进程似乎是异步的。有时在设备旋转时,在 onCreateonWindowFocusChanged(甚至在 onResume)中设置沉浸式标志后,其中一个初始化过程会在之后清除这些标志。

通过我自己的反复试验,我得到了两个解决方案。

  1. 使用 OnSystemUiVisibilityChangeListener 每次清除沉浸式标志后立即重新设置。 (几乎与@Siddarth_G 的 answer 相同)
  2. 利用 Handler.postDelay() 确保在这些初始化过程之后我设置了沉浸式标志。 (几乎与@Luigi_Papardelle 指出的@r3pwn 的https://stackoverflow.com/a/25129542/3501958 相同)

我不知道哪种解决方案是理想的。然而,后者,@r3pwn 的回答表明它来自谷歌的官方示例代码。我认为后一种解决方案非常原始和类似。所以我不知道它是否理想。但似乎没有我想过的那么高级的解决方案。

private static final long INITIAL_HIDE_DELAY = 1000L;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main_activity);

    new Handler(getMainLooper())
            .postDelayed(this::hideSystemUI, INITIAL_HIDE_DELAY);
}

private void hideSystemUI() {
    getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LOW_PROFILE
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    );
}

此解决方案只是在具有足够延迟时间的 onCreate 中设置一次沉浸式标志。