Update (June 11, 2014): Google has fixed this problem since Android 4.4.3. Adjusting the volume won't break the SYSTEM_UI_FLAG_IMMERSIVE_STICKY mode anymore. I would still recommend doing the work around since not everyone have updated to 4.4.3.

So I finally decided to blog about this. I discovered this possible common mistake the same day I got my Android KitKat update on my Nexus 7 (2013). I just wanted to make sure that it IS a common mistake until I post such thing, because it could also be an Android bug as well. Well today, I can confirm that it is in fact a bug.

I've been playing around with one of the new features in Android KitKat, the full-screen immersive mode. So according to the documentation, to enter the new full-screen immersive mode we must call:

	setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

after calling that, you'll get:

Sonic Dash
KitKat easter egg / day dream

now that we're in immersive mode, to bring up the navigation bar (back, home, recent apps buttons) we swipe up from the bottom of the screen. Swipe down from the top of the screen when we want the status bar.

since the flag's name is SYSTEM_UI_FLAG_IMMERSIVE_STICKY you know, "sticky" it should return to immersive mode after some time. Of course it does that.

So here's the problem, when you press the volume keys, you'll get a volume slider panel popped up. Unfortunately, the navigation bar also comes up.

You would think that it would return to full-screen immersive mode after some time since it's "sticky" but it won't.

Now this COULD be just a bug in Android. It might get fixed soon, but in the mean time here's a simple way to fix the problem.

After setting the system UI visibility above, we create a change listener.

private final Runnable hideSystemUiCallback = new Runnable() {
    @Override
    public void run() {
        setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
    }
};
setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
    @Override
    public void onSystemUiVisibilityChange(int visibility) {
        if ((visibility & (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) == 0) {
            hideSystemUiHandler.removeCallbacks(hideSystemUiCallback);
            hideSystemUiHandler.postDelayed(hideSystemUiCallback, HIDE_SYSTEM_UI_DELAY_MILLI);
        }
    }
});

It's similar to handling the low profile state before KitKat actually (link). Anyway, hope you find this tip helpful!