How to preserve immersive mode on orientation change?
Asked Answered
E

4

6

Currently using this block of code in Activity class to enter sticky immersive mode:

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
    }
}

When orientation is switched, the status bar comes back (not even translucent) and stays until dragged, then disappears again. I don't really understand the reason for this behavior, how do I fix it?

Thank you in advance.

Estrous answered 17/2, 2018 at 21:5 Comment(0)
T
5

I faced similar issue when i used what was in the documentation, with just onWindowFocusChanged i tried to hideSystemUi. it worked only on portrait mode when switching to landscape it used to break.

In the documentation i also found OnSystemUiVisibilityChangeListener this will get a callback when system ui is visible here you can check if SYSTEM_UI_FLAG_FULLSCREEN == 0 and again call hideSystemUi().

This worked for me both on landscape and portrait:

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)
}
Twombly answered 14/4, 2020 at 8:23 Comment(1)
You made my day. In combination with #24188228, this solved my problem.Cultured
F
1

I have experienced this symptom beginning from Android 9.0 (API-28).

When I observe these System_UI_FLAG_* flags during initialization process with the decorView being set OnSystemUiVisibilityChangeListener, the underlying processes seem to be asynchronous. Sometimes when device rotation, after you set immersive flags in onCreate or in onWindowFocusChanged (or even in onResume), one of the initialization process clears those flags afterwards.

By my own trial-and-error, I got two solutions.

  1. Use OnSystemUiVisibilityChangeListener to re-set immersive flags every time as soon as they are cleared. (almost same as @Siddarth_G's answer)
  2. Utilize Handler.postDelay() to make sure that my setting immersive flags after those initialization processes. (almost same as @r3pwn's https://mcmap.net/q/422407/-sticky-immersive-mode-disabled-after-soft-keyboard-shown pointed by @Luigi_Papardelle)

I didn't know which solution was ideal. However, the latter, @r3pwn's answer suggested it was from Google's official sample code. I thought the latter solution was quite primitive and analogue. So I didn't know whether it was ideal or not. But it doesn't seem that there is so advanced solution I've ever thought.

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
    );
}

This solution is just setting immersive flags once in onCreate with sufficient delay time.

Fluorocarbon answered 26/1, 2021 at 9:17 Comment(0)
S
0

I think the only way to hide toolbar

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
    }
}
Steeplechase answered 18/2, 2018 at 2:10 Comment(1)
I want to hide status bar, not toolbar. Thanks though!Estrous
I
0

I just tried this, and it seems to work really well:

@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);
}
Impale answered 15/4, 2019 at 17:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.