public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { this.getWindow().getDecorView().setSystemUiVisibility(getSystemUiFlags()); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } private static int getSystemUiFlags() { return View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; } }
After first start

After volume buttons pressed or after recent apps pressed twice

I saw QuickPic app doesn't have this bug. I wonder how they omitted it.
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:
- When getting the focus
- In onResume
- In the OnSystemUiVisibilityChangeListener listener
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().