Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e17a3c47 authored by Tiger Huang's avatar Tiger Huang Committed by Android (Google) Code Review
Browse files

Merge "Let action bar background extend into system insets" into main

parents 14099d9a 7d409b07
Loading
Loading
Loading
Loading
+8 −10
Original line number Diff line number Diff line
@@ -93,8 +93,7 @@ public class ActionBarContainer extends FrameLayout {
        if (bg != null) {
            bg.setCallback(this);
            if (mActionBarView != null) {
                mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(),
                        mActionBarView.getRight(), mActionBarView.getBottom());
                bg.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
            }
        }
        setWillNotDraw(mIsSplit ? mSplitBackground == null :
@@ -293,6 +292,7 @@ public class ActionBarContainer extends FrameLayout {
        if (mActionBarView == null) return;

        if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
            final int verticalPadding = getPaddingTop() + getPaddingBottom();
            int nonTabMaxHeight = 0;
            final int childCount = getChildCount();
            for (int i = 0; i < childCount; i++) {
@@ -307,7 +307,9 @@ public class ActionBarContainer extends FrameLayout {
            final int maxHeight = mode == MeasureSpec.AT_MOST ?
                    MeasureSpec.getSize(heightMeasureSpec) : Integer.MAX_VALUE;
            setMeasuredDimension(getMeasuredWidth(),
                    Math.min(nonTabMaxHeight + getMeasuredHeightWithMargins(mTabContainer),
                    Math.min(
                            verticalPadding + nonTabMaxHeight
                                    + getMeasuredHeightWithMargins(mTabContainer),
                            maxHeight));
        }
    }
@@ -335,13 +337,9 @@ public class ActionBarContainer extends FrameLayout {
            }
        } else {
            if (mBackground != null) {
                if (mActionBarView.getVisibility() == View.VISIBLE) {
                    mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(),
                            mActionBarView.getRight(), mActionBarView.getBottom());
                } else if (mActionContextView != null &&
                        mActionContextView.getVisibility() == View.VISIBLE) {
                    mBackground.setBounds(mActionContextView.getLeft(), mActionContextView.getTop(),
                            mActionContextView.getRight(), mActionContextView.getBottom());
                if ((mActionBarView.getVisibility() == View.VISIBLE) || (mActionContextView != null
                        && mActionContextView.getVisibility() == View.VISIBLE)) {
                    mBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
                } else {
                    mBackground.setBounds(0, 0, 0, 0);
                }
+98 −26
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
@@ -77,10 +78,13 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
    private final Rect mBaseContentInsets = new Rect();
    private final Rect mLastBaseContentInsets = new Rect();
    private final Rect mContentInsets = new Rect();
    private final Rect mSystemInsets = new Rect();
    private WindowInsets mBaseInnerInsets = WindowInsets.CONSUMED;
    private WindowInsets mLastBaseInnerInsets = WindowInsets.CONSUMED;
    private WindowInsets mInnerInsets = WindowInsets.CONSUMED;
    private WindowInsets mLastInnerInsets = WindowInsets.CONSUMED;
    private boolean mDecorFitsSystemWindows = true;
    private boolean mActionBarExtendsIntoSystemInsets = false;

    private ActionBarVisibilityCallback mActionBarVisibilityCallback;

@@ -268,7 +272,8 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
            // We want the bar to be visible if it is not being hidden,
            // or the app has not turned on a stable UI mode (meaning they
            // are performing explicit layout around the action bar).
            mActionBarVisibilityCallback.enableContentAnimations(!stable);
            mActionBarVisibilityCallback.enableContentAnimations(
                    !stable && !mActionBarExtendsIntoSystemInsets);
            if (barVisible || !stable) mActionBarVisibilityCallback.showForSystem();
            else mActionBarVisibilityCallback.hideForSystem();
        }
@@ -288,25 +293,56 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
        }
    }

    private boolean applyInsets(View view, Rect insets, boolean left, boolean top,
            boolean bottom, boolean right) {
        boolean changed = false;
    private boolean applyInsets(View view, Rect insets, boolean toPadding,
            boolean left, boolean top, boolean bottom, boolean right) {
        boolean changed;
        if (toPadding) {
            changed = setMargin(view, left, top, bottom, right, 0, 0, 0, 0);
            changed |= setPadding(view, left, top, bottom, right,
                    insets.left, insets.top, insets.right, insets.bottom);
        } else {
            changed = setPadding(view, left, top, bottom, right, 0, 0, 0, 0);
            changed |= setMargin(view, left, top, bottom, right,
                    insets.left, insets.top, insets.right, insets.bottom);
        }
        return changed;
    }

    private boolean setPadding(View view, boolean left, boolean top, boolean bottom, boolean right,
            int l, int t, int r, int b) {
        if ((left && view.getPaddingLeft() != l)
                || (top && view.getPaddingTop() != t)
                || (right && view.getPaddingRight() != r)
                || (bottom && view.getPaddingBottom() != b)) {
            view.setPadding(
                    left ? l : view.getPaddingLeft(),
                    top ? t : view.getPaddingTop(),
                    right ? r : view.getPaddingRight(),
                    bottom ? b : view.getPaddingBottom());
            return true;
        }
        return false;
    }

    private boolean setMargin(View view, boolean left, boolean top, boolean bottom, boolean right,
            int l, int t, int r, int b) {
        LayoutParams lp = (LayoutParams) view.getLayoutParams();
        if (left && lp.leftMargin != insets.left) {
        boolean changed = false;
        if (left && lp.leftMargin != l) {
            changed = true;
            lp.leftMargin = insets.left;
            lp.leftMargin = l;
        }
        if (top && lp.topMargin != insets.top) {
        if (top && lp.topMargin != t) {
            changed = true;
            lp.topMargin = insets.top;
            lp.topMargin = t;
        }
        if (right && lp.rightMargin != insets.right) {
        if (right && lp.rightMargin != r) {
            changed = true;
            lp.rightMargin = insets.right;
            lp.rightMargin = r;
        }
        if (bottom && lp.bottomMargin != insets.bottom) {
        if (bottom && lp.bottomMargin != b) {
            changed = true;
            lp.bottomMargin = insets.bottom;
            lp.bottomMargin = b;
        }
        return changed;
    }
@@ -316,12 +352,28 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
        pullChildren();

        final int vis = getWindowSystemUiVisibility();
        final Rect systemInsets = insets.getSystemWindowInsetsAsRect();
        final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;
        final boolean layoutIntoSystemInsets = (vis & SYSTEM_UI_LAYOUT_FLAGS) != 0;
        mDecorFitsSystemWindows = hasContentOnApplyWindowInsetsListener();

        // Only extend action bar into system insets area if the app doesn't fit system insets.
        mActionBarExtendsIntoSystemInsets =
                !mDecorFitsSystemWindows || (stable && layoutIntoSystemInsets);

        if (mActionBarVisibilityCallback != null) {
            mActionBarVisibilityCallback.enableContentAnimations(
                    !stable && !mActionBarExtendsIntoSystemInsets);
        }

        final Insets sysInsets = insets.getSystemWindowInsets();
        mSystemInsets.set(sysInsets.left, sysInsets.top, sysInsets.right, sysInsets.bottom);

        // The top and bottom action bars are always within the content area.
        boolean changed = applyInsets(mActionBarTop, systemInsets, true, true, false, true);
        boolean changed = applyInsets(mActionBarTop, mSystemInsets,
                mActionBarExtendsIntoSystemInsets, true, true, false, true);
        if (mActionBarBottom != null) {
            changed |= applyInsets(mActionBarBottom, systemInsets, true, false, true, true);
            changed |= applyInsets(mActionBarBottom, mSystemInsets,
                    mActionBarExtendsIntoSystemInsets, true, false, true, true);
        }

        // Cannot use the result of computeSystemWindowInsets, because that consumes the
@@ -406,6 +458,9 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
            // This is the standard space needed for the action bar.  For stable measurement,
            // we can't depend on the size currently reported by it -- this must remain constant.
            topInset = mActionBarHeight;
            if (mActionBarExtendsIntoSystemInsets) {
                topInset += mSystemInsets.top;
            }
            if (mHasNonEmbeddedTabs) {
                final View tabs = mActionBarTop.getTabContainer();
                if (tabs != null) {
@@ -424,6 +479,9 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
            if (mActionBarBottom != null) {
                if (stable) {
                    bottomInset = mActionBarHeight;
                    if (mActionBarExtendsIntoSystemInsets) {
                        bottomInset += mSystemInsets.bottom;
                    }
                } else {
                    bottomInset = mActionBarBottom.getMeasuredHeight();
                }
@@ -436,13 +494,26 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
        // overlay.
        mContentInsets.set(mBaseContentInsets);
        mInnerInsets = mBaseInnerInsets;
        if (!mOverlayMode && !stable && hasContentOnApplyWindowInsetsListener()) {
        if (!mOverlayMode && !stable && mDecorFitsSystemWindows) {
            if (mActionBarExtendsIntoSystemInsets) {
                mContentInsets.top = Math.max(mContentInsets.top, topInset);
                mContentInsets.bottom = Math.max(mContentInsets.bottom, bottomInset);
            } else {
                mContentInsets.top += topInset;
                mContentInsets.bottom += bottomInset;
            }
            // Content view has been shrunk, shrink all insets to match.
            mInnerInsets = mInnerInsets.inset(0 /* left */, topInset, 0 /* right */, bottomInset);
        } else {
            // Add ActionBar to system window inset, but leave other insets untouched.
            if (mActionBarExtendsIntoSystemInsets) {
                mInnerInsets = mInnerInsets.replaceSystemWindowInsets(
                        mInnerInsets.getSystemWindowInsetLeft(),
                        Math.max(mInnerInsets.getSystemWindowInsetTop(), topInset),
                        mInnerInsets.getSystemWindowInsetRight(),
                        Math.max(mInnerInsets.getSystemWindowInsetBottom(), bottomInset)
                );
            } else {
                mInnerInsets = mInnerInsets.replaceSystemWindowInsets(
                        mInnerInsets.getSystemWindowInsetLeft(),
                        mInnerInsets.getSystemWindowInsetTop() + topInset,
@@ -450,7 +521,8 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
                        mInnerInsets.getSystemWindowInsetBottom() + bottomInset
                );
            }
        applyInsets(mContent, mContentInsets, true, true, true, true);
        }
        applyInsets(mContent, mContentInsets, false /* toPadding */, true, true, true, true);

        if (!mLastInnerInsets.equals(mInnerInsets)) {
            // If the inner insets have changed, we need to dispatch this down to
+14 −5
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.view.DisplayCutout.NO_CUTOUT;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.makeMeasureSpec;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.is;
@@ -69,6 +70,7 @@ public class ActionBarOverlayLayoutTest {

    private ViewGroup mContent;
    private ViewGroup mActionBarTop;
    private ViewGroup mActionBarView;
    private Toolbar mToolbar;
    private FakeOnApplyWindowListener mContentInsetsListener;

@@ -86,15 +88,22 @@ public class ActionBarOverlayLayoutTest {
        mContentInsetsListener = new FakeOnApplyWindowListener();
        mContent.setOnApplyWindowInsetsListener(mContentInsetsListener);

        // mActionBarView and mToolbar are supposed to be the same view. Here makes mToolbar a child
        // of mActionBarView is to control the height of mActionBarView. In this way, the child
        // views of mToolbar won't affect the measurement of mActionBarView or mActionBarTop.
        mActionBarView = new FrameLayout(mContext);
        mActionBarView.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, 20));

        mToolbar = new Toolbar(mContext);
        mToolbar.setId(com.android.internal.R.id.action_bar);
        mActionBarView.addView(mToolbar);

        mActionBarTop = new ActionBarContainer(mContext);
        mActionBarTop.setId(com.android.internal.R.id.action_bar_container);
        mActionBarTop.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, 20));
        mActionBarTop.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
        mActionBarTop.addView(mActionBarView);
        mLayout.addView(mActionBarTop);
        mLayout.setActionBarHeight(20);

        mToolbar = new Toolbar(mContext);
        mToolbar.setId(com.android.internal.R.id.action_bar);
        mActionBarTop.addView(mToolbar);
    }

    @Test