setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) does not work

Timmmm picture Timmmm · Jan 6, 2013 · Viewed 40.7k times · Source

I've been battling with setSystemUiVisibility() to try to hide the soft navigation buttons for a while (for a video player). It does not seem to work as advertised. Here is my code, inside a visible FrameLayout.

void setNavVisibility(boolean visible)
{
    int newVis = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    if (!visible)
    {
        newVis |= SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
    }
    setSystemUiVisibility(newVis);
}

Slightly modified from the SDK example:

    void setNavVisibility(boolean visible) {
        int newVis = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | SYSTEM_UI_FLAG_LAYOUT_STABLE;
        if (!visible) {
            newVis |= SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN
                    | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        }

Neither do anything when called. I had some success when I called them from a different View, but the documentation doesn't mention that the View you are calling from has any effect? I assume that the documentation is (surprise surprise) somewhat lacking here. Does anyone know what's really going on?

Answer

Timmmm picture Timmmm · Jan 6, 2013

Hmm apparently I duplicated my own question! But anyway I found the answer: After reading the source code - which is often the only way to find things out in Android-land - I discovered the following undocumented fact:

setSystemUiVisibility() only has effect when the view you call it from is visible!

Even more: The view in which you call setSystemUiVisibility() must remain visible for the nav bar to remain hidden. Thanks for documenting that guys, really great.

Here is the relevant code, in View.java.

void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
    if ((visibility & VISIBILITY_MASK) == VISIBLE) {
        if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
            attachInfo.mKeepScreenOn = true;
        }
        attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
            attachInfo.mHasSystemUiListeners = true;
        }
    }
}