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

Commit 9c9aec72 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Fix issue #8311263: Corrupted UI across all tabs in People app" into jb-mr2-dev

parents 25a3b1dd 1dc5f927
Loading
Loading
Loading
Loading
+172 −33
Original line number Diff line number Diff line
@@ -16,33 +16,42 @@

package com.android.internal.widget;

import android.view.ViewGroup;
import com.android.internal.app.ActionBarImpl;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;

/**
 * Special layout for the containing of an overlay action bar (and its
 * content) to correctly handle fitting system windows when the content
 * has request that its layout ignore them.
 */
public class ActionBarOverlayLayout extends FrameLayout {
public class ActionBarOverlayLayout extends ViewGroup {
    private int mActionBarHeight;
    private ActionBarImpl mActionBar;
    private int mWindowVisibility = View.VISIBLE;

    // The main UI elements that we handle the layout of.
    private View mContent;
    private View mActionBarTop;
    private View mActionBarBottom;

    // Some interior UI elements.
    private ActionBarContainer mContainerView;
    private ActionBarView mActionView;
    private View mActionBarBottom;

    private boolean mOverlayMode;
    private int mLastSystemUiVisibility;
    private final Rect mLocalInsets = new Rect();
    private final Rect mBaseContentInsets = new Rect();
    private final Rect mLastBaseContentInsets = new Rect();
    private final Rect mContentInsets = new Rect();
    private final Rect mBaseInnerInsets = new Rect();
    private final Rect mInnerInsets = new Rect();
    private final Rect mLastInnerInsets = new Rect();

    static final int[] mActionBarSizeAttr = new int [] {
            com.android.internal.R.attr.actionBarSize
@@ -139,7 +148,7 @@ public class ActionBarOverlayLayout extends FrameLayout {
    private boolean applyInsets(View view, Rect insets, boolean left, boolean top,
            boolean bottom, boolean right) {
        boolean changed = false;
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams)view.getLayoutParams();
        LayoutParams lp = (LayoutParams)view.getLayoutParams();
        if (left && lp.leftMargin != insets.left) {
            changed = true;
            lp.leftMargin = insets.left;
@@ -168,52 +177,163 @@ public class ActionBarOverlayLayout extends FrameLayout {

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

        mBaseInnerInsets.set(insets);
        computeFitSystemWindows(mBaseInnerInsets, mBaseContentInsets);
        if (!mLastBaseContentInsets.equals(mBaseContentInsets)) {
            changed = true;
            mLastBaseContentInsets.set(mBaseContentInsets);
        }

        int topSpace = 0;
        if (stable || mActionBarTop.getVisibility() == VISIBLE) {
            // This is the space needed on top of the window for the action bar.
            topSpace = mActionBarHeight;
        if (changed) {
            requestLayout();
        }

        // We don't do any more at this point.  To correctly compute the content/inner
        // insets in all cases, we need to know the measured size of the various action
        // bar elements.  fitSystemWindows() happens before the measure pass, so we can't
        // do that here.  Instead we will take this up in onMeasure().
        return true;
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int maxHeight = 0;
        int maxWidth = 0;
        int childState = 0;

        int topInset = 0;
        int bottomInset = 0;

        measureChildWithMargins(mActionBarTop, widthMeasureSpec, 0, heightMeasureSpec, 0);
        LayoutParams lp = (LayoutParams) mActionBarTop.getLayoutParams();
        maxWidth = Math.max(maxWidth,
                mActionBarTop.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
        maxHeight = Math.max(maxHeight,
                mActionBarTop.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
        childState = combineMeasuredStates(childState, mActionBarTop.getMeasuredState());

        measureChildWithMargins(mActionBarBottom, widthMeasureSpec, 0, heightMeasureSpec, 0);
        lp = (LayoutParams) mActionBarBottom.getLayoutParams();
        maxWidth = Math.max(maxWidth,
                mActionBarBottom.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
        maxHeight = Math.max(maxHeight,
                mActionBarBottom.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
        childState = combineMeasuredStates(childState, mActionBarBottom.getMeasuredState());

        final int vis = getWindowSystemUiVisibility();
        final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;

        if (stable) {
            // 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 (mActionBar != null && mActionBar.hasNonEmbeddedTabs()) {
                View tabs = mContainerView.getTabContainer();
            if (tabs != null && (stable || tabs.getVisibility() == VISIBLE)) {
                if (tabs != null) {
                    // If tabs are not embedded, increase space on top to account for them.
                topSpace += mActionBarHeight;
                    topInset += mActionBarHeight;
                }
            }
        } else if (mActionBarTop.getVisibility() == VISIBLE) {
            // This is the space needed on top of the window for all of the action bar
            // and tabs.
            topInset = mActionBarTop.getMeasuredHeight();
        }

        int bottomSpace = 0;
        if (mActionView.isSplitActionBar()) {
            if ((mActionBarBottom != null
                    && (stable || mActionBarBottom.getVisibility() == VISIBLE))) {
            // If action bar is split, adjust bottom insets for it.
                bottomSpace = mActionBarHeight;
            if (stable) {
                bottomInset = mActionBarHeight;
            } else {
                bottomInset = mActionBarBottom.getMeasuredHeight();
            }
        }

        // If the window has not requested system UI layout flags, we need to
        // make sure its content is not being covered by system UI...  though it
        // will still be covered by the action bar since they have requested it to
        // will still be covered by the action bar if they have requested it to
        // overlay.
        boolean res = computeFitSystemWindows(insets, mLocalInsets);
        mContentInsets.set(mBaseContentInsets);
        mInnerInsets.set(mBaseInnerInsets);
        if (!mOverlayMode && !stable) {
            mLocalInsets.top += topSpace;
            mLocalInsets.bottom += bottomSpace;
            mContentInsets.top += topInset;
            mContentInsets.bottom += bottomInset;
        } else {
            insets.top += topSpace;
            insets.bottom += bottomSpace;
            mInnerInsets.top += topInset;
            mInnerInsets.bottom += bottomInset;
        }
        changed |= applyInsets(mContent, mLocalInsets, true, true, true, true);
        applyInsets(mContent, mContentInsets, true, true, true, true);

        if (changed) {
            requestLayout();
        if (!mLastInnerInsets.equals(mInnerInsets)) {
            // If the inner insets have changed, we need to dispatch this down to
            // the app's fitSystemWindows().  We do this before measuring the content
            // view to keep the same semantics as the normal fitSystemWindows() call.
            mLastInnerInsets.set(mInnerInsets);
            super.fitSystemWindows(mInnerInsets);
        }

        super.fitSystemWindows(insets);
        return true;
        measureChildWithMargins(mContent, widthMeasureSpec, 0, heightMeasureSpec, 0);
        lp = (LayoutParams) mContent.getLayoutParams();
        maxWidth = Math.max(maxWidth,
                mContent.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
        maxHeight = Math.max(maxHeight,
                mContent.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
        childState = combineMeasuredStates(childState, mContent.getMeasuredState());

        // Account for padding too
        maxWidth += getPaddingLeft() + getPaddingRight();
        maxHeight += getPaddingTop() + getPaddingBottom();

        // Check against our minimum height and width
        maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());

        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
                resolveSizeAndState(maxHeight, heightMeasureSpec,
                        childState << MEASURED_HEIGHT_STATE_SHIFT));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final int count = getChildCount();

        final int parentLeft = getPaddingLeft();
        final int parentRight = right - left - getPaddingRight();

        final int parentTop = getPaddingTop();
        final int parentBottom = bottom - top - getPaddingBottom();

        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();

                final int width = child.getMeasuredWidth();
                final int height = child.getMeasuredHeight();

                int childLeft = parentLeft + lp.leftMargin;
                int childTop;
                if (child == mActionBarBottom) {
                    childTop = parentBottom - height - lp.bottomMargin;
                } else {
                    childTop = parentTop + lp.topMargin;
                }

                child.layout(childLeft, childTop, childLeft + width, childTop + height);
            }
        }
    }

    void pullChildren() {
@@ -226,4 +346,23 @@ public class ActionBarOverlayLayout extends FrameLayout {
            mActionBarBottom = findViewById(com.android.internal.R.id.split_action_bar);
        }
    }


    public static class LayoutParams extends MarginLayoutParams {
        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }

        public LayoutParams(ViewGroup.LayoutParams source) {
            super(source);
        }

        public LayoutParams(ViewGroup.MarginLayoutParams source) {
            super(source);
        }
    }
}
+1 −3
Original line number Diff line number Diff line
@@ -29,8 +29,7 @@ This is an optimized layout for a screen with the Action Bar enabled.
        android:layout_height="match_parent" />
    <LinearLayout android:id="@+id/top_action_bar"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_gravity="top">
                  android:layout_height="wrap_content">
        <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
@@ -57,7 +56,6 @@ This is an optimized layout for a screen with the Action Bar enabled.
    <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_gravity="bottom"
                  style="?android:attr/actionBarSplitStyle"
                  android:visibility="gone"
                  android:gravity="center"/>