public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
this.getWindow().getDecorView().setSyste
The following code works for me:
public void updateUI() {
final View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
decorView.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 called the listener on onCreate
and onResume
methods:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
updateUI();
}
@Override
public void onResume() {
super.onResume();
updateUI();
}
I had the same problem, and I solved it with a simple workaround. Even though I couldn't find the theoretical reason of this workaround, but it worked for me anyway.
It seems like when a volume button is pressed, the 'flags' related to the 'immersive mode' are cleared. And I think that's why the immersive mode is disabled and the immersive mode is not restored automatically.
Therefore, I tried to set the 'flags' after pressing the volume button with 'runnable' object.
So, it works like this:
immersive mode -> volume button pressed(flags cleared) -> 500ms later, the runnable object sets the flags again -> immersive mode restored
1. First, define the runnable object to set the flags
private Runnable decor_view_settings = new Runnable()
{
public void run()
{
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);
}
};
2. Post the runnable object with some delay to a handler when a volume button is pressed
private Handler mHandler = new Handler();
...
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if(keyCode == KeyEvent.KEYCODE_BACK)
{
finish();
}
else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP)
{
mHandler.postDelayed(decor_view_settings, 500);
}
return super.onKeyDown(keyCode, event);
}
I just delayed it for 500ms with no reason, it's not important.
3. The basic code for immersive mode with runnable object
@Override
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
if(hasFocus)
{
mHandler.post(decor_view_settings);
}
}
It worked perfectly on my app.
So, when I press a volume button, the immersive mode is disabled and the volume rocker pops up.
after a few seconds, the volume rocker disappears and so does the status bar and the navigation bar.
Hope this work for you.
My solution is to set the UI-Visibility flags in three places:
The third solved my problem. The others might not be needed, but I left them. This is what is looks like:
private void setupMainWindowDisplayMode() {
View decorView = setSystemUiVisilityMode();
decorView.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
setSystemUiVisilityMode(); // Needed to avoid exiting immersive_sticky when keyboard is displayed
}
});
}
private View setSystemUiVisilityMode() {
View decorView = getWindow().getDecorView();
int options;
options =
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_STICKY;
decorView.setSystemUiVisibility(options);
return decorView;
}
setupMainWindowDisplayMode() gets called in onCreate().