windowSoftInputMode="adjustResize" not working with translucent action/navbar

If you want to customize the insets and you are targeting API level >=21 you can accomplish this without having to create a custom view group. By just setting fitsSystemWindows padding will be applied to your container view by default, which you may not want.

The version checks are built into this method and only devices >= 21 will execute the code inside the lambda. Kotlin example:

ViewCompat.setOnApplyWindowInsetsListener(container) { view, insets ->
  insets.replaceSystemWindowInsets(0, 0, 0, insets.systemWindowInsetBottom).apply {
    ViewCompat.onApplyWindowInsets(view, this)
  }
}

Make sure your layout still sets the fitsSystemWindows flag otherwise the window insets listener will not be called.

<FrameLayout
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    />

These sources are helpful:

https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec https://medium.com/@azizbekian/windowinsets-24e241d4afb9


There's a related bug report here. I've found a workaround that, from limited testing, seems to do the trick with no repercussions. Add a custom implementation of your root ViewGroup (I almost always am using FrameLayout, so this is what I've tested with) with the logic below. Then, use this custom layout in place of your root layout, and ensure you set android:fitsSystemWindows="true". You can then just call getInsets() any time after layout (e.g. add an OnPreDrawListener) to adjust the rest of your layout to account for the system insets, if desired.

import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import org.jetbrains.annotations.NotNull;

/**
 * @author Kevin
 *         Date Created: 3/7/14
 *
 * https://code.google.com/p/android/issues/detail?id=63777
 * 
 * When using a translucent status bar on API 19+, the window will not
 * resize to make room for input methods (i.e.
 * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} and
 * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_PAN} are
 * ignored).
 * 
 * To work around this; override {@link #fitSystemWindows(android.graphics.Rect)},
 * capture and override the system insets, and then call through to FrameLayout's
 * implementation.
 * 
 * For reasons yet unknown, modifying the bottom inset causes this workaround to
 * fail. Modifying the top, left, and right insets works as expected.
 */
public final class CustomInsetsFrameLayout extends FrameLayout {
    private int[] mInsets = new int[4];

    public CustomInsetsFrameLayout(Context context) {
        super(context);
    }

    public CustomInsetsFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public final int[] getInsets() {
        return mInsets;
    }

    @Override
    protected final boolean fitSystemWindows(@NotNull Rect insets) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // Intentionally do not modify the bottom inset. For some reason, 
            // if the bottom inset is modified, window resizing stops working.
            // TODO: Figure out why.

            mInsets[0] = insets.left;
            mInsets[1] = insets.top;
            mInsets[2] = insets.right;

            insets.left = 0;
            insets.top = 0;
            insets.right = 0;
        }

        return super.fitSystemWindows(insets);
    }
}

Since fitSystemWindows was deprecated, please refer to the answer below to complete the workaround.


You are missing the following property:

android:fitsSystemWindows="true"

in the root RelativeLayout of the fragment .xml layout.

Update:

Last year there was an interesting talk by Chris Bane that explains in good detail how this works:

https://www.youtube.com/watch?v=_mGDMVRO3iE


@kcoppock answer is really helpful, but fitSystemWindows was deprecated in API level 20

So since API 20 (KITKAT_WATCH) you should override onApplyWindowInsets

@Override
public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
        return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,
                insets.getSystemWindowInsetBottom()));
    } else {
        return insets;
    }
}