I'm facing a problem when using immersive mode. Here is the code I put on all activities:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
);
}
}
The navigationBar
and statusBar
are invisible, this is good.
The problem is that every time I go to another activity, the navigationBar
appears, then disappears. I would like that the navigationBar
to not appear like that.
The simplest working way is to create a base activity class like the following:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
enableImmersiveMode();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus) {
enableImmersiveMode();
}
}
protected void enableImmersiveMode() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
);
}
}
}
And all activities that should work in immersive mode should inherit from above base class.
I've just tested it. It prevents an on-screen menu to hide and reveal while changing activities.
If you invoque this short of code in method onCreate of activity like the next example:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hideSystemUI();
...
}
// This snippet hides the system bars.
private void hideSystemUI() {
// Set the IMMERSIVE flag.
// Set the content to appear under the system bars so that the content
// doesn't resize when the system bars hide and show.
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
| View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE);
}
And you must invoke the method on onWindowFocusChanged too.
I hope this help you =)
maybe it's late but right now I faced same issue as you, and stumbled upon this post. By curiosity I found solution that worked for me. I manually called function "onWindowFocusChanged" and passed the "true" parameter. I called that function in OnCreate, before "setContentView(R.layout.activity_main);". That executed the function and set immersive mode (fullscreen), before layout was added, and now I don't see hiding animation of navigation and status bars. I hope that I helped you.
This is the code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onWindowFocusChanged(true);
setContentView(R.layout.activity_main);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}
}
I was also faced with this issue. It seems there is no way to stop Android from showing the navigation bar again after the configuration changes.
What's worse, it is also not guaranteed when exactly the system UI will be restored. According to my tests on some devices the nav bar can reappear even after onWindowFocusChanged
and onResume
have been called.
The only reliable way I've found to prevent undesired UI reappearing is to add isInFullScreenMode
boolean flag and implement View.OnSystemUiVisibilityChangeListener
something like this:
@Override
public void onSystemBarsVisible() {
if (isInFullScreenMode) {
// If Android presented system bars
// but our app doesn't need them at this point
// just call hideSystemUi() again
hideSystemUi();
return;
}
}
@Override
public void onSystemBarsHidden() {
if (!isInFullScreenMode) {
// Similar technique as shown above
showSystemUi();
return;
}
}
Of course, sometimes on rotation we can see how the system bars quickly appear and disappear. But at least we can be sure that our app's UI state will be reliably restored.
Edit: To prevent possible confusion (as can be seen in the comments), I will clarify a couple of things:
onSystemBarsVisible
and onSystemBarsHidden
are custom methods which were defined in my app. You won't find them in Android frameworks;override
keywords are used here because these methods were part of a contract (interface);fun onSystemUiVisibilityChange(visibility: Int) {
if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
// The system bars are visible
onSystemBarsVisible()
} else {
// The system bars are NOT visible.
onSystemBarsHidden()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With