What exactly does fitsSystemWindows do?

I’m struggling to understand the concept of fitsSystemWindows as depending on the view it does different things. According to the official documentation it’s a

Boolean internal attribute to adjust view layout based on system windows such as the status bar. If true, adjusts the padding of this view to leave space for the system windows.

Now, checking the View.java class I can see that when set to true, the window insets (status bar, navigation bar…) are applied to the view paddings, which works according to the documentation quoted above. This is the relevant part of the code:

private boolean fitSystemWindowsInt(Rect insets) {
    if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        Rect localInsets = sThreadLocal.get();
        if (localInsets == null) {
            localInsets = new Rect();
            sThreadLocal.set(localInsets);
        }
        boolean res = computeFitSystemWindows(insets, localInsets);
        mUserPaddingLeftInitial = localInsets.left;
        mUserPaddingRightInitial = localInsets.right;
        internalSetPadding(localInsets.left, localInsets.top,
                localInsets.right, localInsets.bottom);
        return res;
    }
    return false;
}

With the new Material design there are new classes which make extensive use of this flag and this is where the confusion comes. In many sources fitsSystemWindows is mentioned as the flag to set to lay the view behind the system bars. See here.

The documentation in ViewCompat.java for setFitsSystemWindows says:

Sets whether or not this view should account for system screen decorations such as the status bar and inset its content; that is, controlling whether the default implementation of {@link View#fitSystemWindows(Rect)} will be executed. See that method for more details.

According to this, fitsSystemWindows simply means that the function fitsSystemWindows() will be executed? The new Material classes seem to just use this for drawing under the status bar. If we look at DrawerLayout.java‘s code, we can see this:

if (ViewCompat.getFitsSystemWindows(this)) {
        IMPL.configureApplyInsets(this);
        mStatusBarBackground = IMPL.getDefaultStatusBarBackground(context);
    }

public static void configureApplyInsets(View drawerLayout) {
    if (drawerLayout instanceof DrawerLayoutImpl) {
        drawerLayout.setOnApplyWindowInsetsListener(new InsetsListener());
        drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    }
}

And we see the same pattern in the new CoordinatorLayout or AppBarLayout.

Doesn’t this work in the exact opposite way as the documentation for fitsSystemWindows? In the last cases, it means draw behind the system bars.

However, if you want a FrameLayout to draw itself behind the status bar, setting fitsSystemWindows to true does not do the trick as the default implementation does what’s documented initially. You have to override it and add the same flags as the other mentioned classes. Am I missing something?

Leave a Comment