Reputation: 61
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.
Upvotes: 6
Views: 1691
Reputation: 12483
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.
OnSystemUiVisibilityChangeListener
to re-set immersive flags every time as soon as they are cleared. (almost same as @Siddarth_G's answer)Handler.postDelay()
to make sure that my setting immersive flags after those initialization processes. (almost same as @r3pwn's https://stackoverflow.com/a/25129542/3501958 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.
Upvotes: 1
Reputation: 779
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)
}
Upvotes: 5
Reputation: 23787
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);
}
Upvotes: 0
Reputation: 1268
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
}
}
Upvotes: 0