OSDN Git Service

Revert "Add support for partial view layouts"
authorChet Haase <chet@google.com>
Thu, 3 Dec 2015 15:38:11 +0000 (07:38 -0800)
committerChet Haase <chet@google.com>
Wed, 9 Dec 2015 00:45:23 +0000 (16:45 -0800)
This reverts commit c55d5072ac52cee1811b52406419228fa81119ce.

There were several bugs related to incorrect handling of various
layout issues (layout not being run on containers/views that needed
it), reverting to take another run at it outside of master.

Issue #25980198  requestLayout() sometimes doesn't result in measure/layout for view

Change-Id: Ic0e159cbcf6171652d8fd1bee9ae44a3977cea04

14 files changed:
api/current.txt
api/system-current.txt
api/test-current.txt
core/java/android/view/View.java
core/java/android/view/ViewGroup.java
core/java/android/view/ViewParent.java
core/java/android/view/ViewRootImpl.java
core/java/android/widget/AbsListView.java
core/java/android/widget/FrameLayout.java
core/java/android/widget/LinearLayout.java
core/java/android/widget/ListView.java
core/java/android/widget/TextView.java
core/java/android/widget/Toolbar.java
core/java/com/android/internal/widget/ActionBarOverlayLayout.java

index ca176b6..323d02a 100644 (file)
@@ -40524,7 +40524,6 @@ package android.view {
     method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
     method public void createContextMenu(android.view.ContextMenu);
     method public void destroyDrawingCache();
-    method public final boolean didLayoutParamsChange();
     method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
     method public void dispatchConfigurationChanged(android.content.res.Configuration);
     method public void dispatchDisplayHint(int);
@@ -40750,7 +40749,6 @@ package android.view {
     method public boolean isOpaque();
     method protected boolean isPaddingOffsetRequired();
     method public boolean isPaddingRelative();
-    method public final boolean isPartialLayoutRequested();
     method public boolean isPressed();
     method public boolean isSaveEnabled();
     method public boolean isSaveFromParentEnabled();
@@ -41362,7 +41360,6 @@ package android.view {
     method protected void dispatchThawSelfOnly(android.util.SparseArray<android.os.Parcelable>);
     method protected boolean drawChild(android.graphics.Canvas, android.view.View, long);
     method public void endViewTransition(android.view.View);
-    method public int findDependentLayoutAxes(android.view.View, int);
     method public android.view.View focusSearch(android.view.View, int);
     method public void focusableViewAvailable(android.view.View);
     method public boolean gatherTransparentRegion(android.graphics.Region);
@@ -41429,8 +41426,6 @@ package android.view {
     method public void requestChildFocus(android.view.View, android.view.View);
     method public boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
     method public void requestDisallowInterceptTouchEvent(boolean);
-    method public void requestLayoutForChild(android.view.View);
-    method public void requestPartialLayoutForChild(android.view.View);
     method public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public void requestTransparentRegion(android.view.View);
     method public void scheduleLayoutAnimation();
@@ -41545,7 +41540,6 @@ package android.view {
     method public abstract void childHasTransientStateChanged(android.view.View, boolean);
     method public abstract void clearChildFocus(android.view.View);
     method public abstract void createContextMenu(android.view.ContextMenu);
-    method public abstract int findDependentLayoutAxes(android.view.View, int);
     method public abstract android.view.View focusSearch(android.view.View, int);
     method public abstract void focusableViewAvailable(android.view.View);
     method public abstract boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point);
@@ -41575,16 +41569,12 @@ package android.view {
     method public abstract void requestDisallowInterceptTouchEvent(boolean);
     method public abstract void requestFitSystemWindows();
     method public abstract void requestLayout();
-    method public abstract void requestLayoutForChild(android.view.View);
     method public abstract boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public abstract void requestTransparentRegion(android.view.View);
     method public abstract boolean showContextMenuForChild(android.view.View);
     method public abstract boolean showContextMenuForChild(android.view.View, float, float);
     method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
     method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback, int);
-    field public static final int FLAG_LAYOUT_AXIS_ANY = 3; // 0x3
-    field public static final int FLAG_LAYOUT_AXIS_HORIZONTAL = 1; // 0x1
-    field public static final int FLAG_LAYOUT_AXIS_VERTICAL = 2; // 0x2
   }
 
   public class ViewPropertyAnimator {
@@ -64103,3 +64093,4 @@ package org.xmlpull.v1.sax2 {
   }
 
 }
+
index dcb0852..70a713c 100644 (file)
@@ -42860,7 +42860,6 @@ package android.view {
     method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
     method public void createContextMenu(android.view.ContextMenu);
     method public void destroyDrawingCache();
-    method public final boolean didLayoutParamsChange();
     method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
     method public void dispatchConfigurationChanged(android.content.res.Configuration);
     method public void dispatchDisplayHint(int);
@@ -43086,7 +43085,6 @@ package android.view {
     method public boolean isOpaque();
     method protected boolean isPaddingOffsetRequired();
     method public boolean isPaddingRelative();
-    method public final boolean isPartialLayoutRequested();
     method public boolean isPressed();
     method public boolean isSaveEnabled();
     method public boolean isSaveFromParentEnabled();
@@ -43698,7 +43696,6 @@ package android.view {
     method protected void dispatchThawSelfOnly(android.util.SparseArray<android.os.Parcelable>);
     method protected boolean drawChild(android.graphics.Canvas, android.view.View, long);
     method public void endViewTransition(android.view.View);
-    method public int findDependentLayoutAxes(android.view.View, int);
     method public android.view.View focusSearch(android.view.View, int);
     method public void focusableViewAvailable(android.view.View);
     method public boolean gatherTransparentRegion(android.graphics.Region);
@@ -43765,8 +43762,6 @@ package android.view {
     method public void requestChildFocus(android.view.View, android.view.View);
     method public boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
     method public void requestDisallowInterceptTouchEvent(boolean);
-    method public void requestLayoutForChild(android.view.View);
-    method public void requestPartialLayoutForChild(android.view.View);
     method public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public void requestTransparentRegion(android.view.View);
     method public void scheduleLayoutAnimation();
@@ -43881,7 +43876,6 @@ package android.view {
     method public abstract void childHasTransientStateChanged(android.view.View, boolean);
     method public abstract void clearChildFocus(android.view.View);
     method public abstract void createContextMenu(android.view.ContextMenu);
-    method public abstract int findDependentLayoutAxes(android.view.View, int);
     method public abstract android.view.View focusSearch(android.view.View, int);
     method public abstract void focusableViewAvailable(android.view.View);
     method public abstract boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point);
@@ -43911,16 +43905,12 @@ package android.view {
     method public abstract void requestDisallowInterceptTouchEvent(boolean);
     method public abstract void requestFitSystemWindows();
     method public abstract void requestLayout();
-    method public abstract void requestLayoutForChild(android.view.View);
     method public abstract boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public abstract void requestTransparentRegion(android.view.View);
     method public abstract boolean showContextMenuForChild(android.view.View);
     method public abstract boolean showContextMenuForChild(android.view.View, float, float);
     method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
     method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback, int);
-    field public static final int FLAG_LAYOUT_AXIS_ANY = 3; // 0x3
-    field public static final int FLAG_LAYOUT_AXIS_HORIZONTAL = 1; // 0x1
-    field public static final int FLAG_LAYOUT_AXIS_VERTICAL = 2; // 0x2
   }
 
   public class ViewPropertyAnimator {
index da02754..21e1551 100644 (file)
@@ -40526,7 +40526,6 @@ package android.view {
     method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
     method public void createContextMenu(android.view.ContextMenu);
     method public void destroyDrawingCache();
-    method public final boolean didLayoutParamsChange();
     method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
     method public void dispatchConfigurationChanged(android.content.res.Configuration);
     method public void dispatchDisplayHint(int);
@@ -40752,7 +40751,6 @@ package android.view {
     method public boolean isOpaque();
     method protected boolean isPaddingOffsetRequired();
     method public boolean isPaddingRelative();
-    method public final boolean isPartialLayoutRequested();
     method public boolean isPressed();
     method public boolean isSaveEnabled();
     method public boolean isSaveFromParentEnabled();
@@ -41364,7 +41362,6 @@ package android.view {
     method protected void dispatchThawSelfOnly(android.util.SparseArray<android.os.Parcelable>);
     method protected boolean drawChild(android.graphics.Canvas, android.view.View, long);
     method public void endViewTransition(android.view.View);
-    method public int findDependentLayoutAxes(android.view.View, int);
     method public android.view.View focusSearch(android.view.View, int);
     method public void focusableViewAvailable(android.view.View);
     method public boolean gatherTransparentRegion(android.graphics.Region);
@@ -41431,8 +41428,6 @@ package android.view {
     method public void requestChildFocus(android.view.View, android.view.View);
     method public boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
     method public void requestDisallowInterceptTouchEvent(boolean);
-    method public void requestLayoutForChild(android.view.View);
-    method public void requestPartialLayoutForChild(android.view.View);
     method public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public void requestTransparentRegion(android.view.View);
     method public void scheduleLayoutAnimation();
@@ -41547,7 +41542,6 @@ package android.view {
     method public abstract void childHasTransientStateChanged(android.view.View, boolean);
     method public abstract void clearChildFocus(android.view.View);
     method public abstract void createContextMenu(android.view.ContextMenu);
-    method public abstract int findDependentLayoutAxes(android.view.View, int);
     method public abstract android.view.View focusSearch(android.view.View, int);
     method public abstract void focusableViewAvailable(android.view.View);
     method public abstract boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point);
@@ -41577,16 +41571,12 @@ package android.view {
     method public abstract void requestDisallowInterceptTouchEvent(boolean);
     method public abstract void requestFitSystemWindows();
     method public abstract void requestLayout();
-    method public abstract void requestLayoutForChild(android.view.View);
     method public abstract boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public abstract void requestTransparentRegion(android.view.View);
     method public abstract boolean showContextMenuForChild(android.view.View);
     method public abstract boolean showContextMenuForChild(android.view.View, float, float);
     method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback);
     method public abstract android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback, int);
-    field public static final int FLAG_LAYOUT_AXIS_ANY = 3; // 0x3
-    field public static final int FLAG_LAYOUT_AXIS_HORIZONTAL = 1; // 0x1
-    field public static final int FLAG_LAYOUT_AXIS_VERTICAL = 2; // 0x2
   }
 
   public class ViewPropertyAnimator {
index 6dd87a0..183ccf3 100644 (file)
@@ -83,7 +83,6 @@ import android.view.AccessibilityIterators.TextSegmentIterator;
 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
 import android.view.AccessibilityIterators.WordTextSegmentIterator;
 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
-import android.view.ViewGroup.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityEventSource;
 import android.view.accessibility.AccessibilityManager;
@@ -2423,8 +2422,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      *                    1              PFLAG3_SCROLL_INDICATOR_END
      *                   1               PFLAG3_ASSIST_BLOCKED
      *            1111111                PFLAG3_POINTER_ICON_MASK
-     *           1                       PFLAG3_PARTIAL_LAYOUT_REQUESTED
-     *          1                        PFLAG3_LAYOUT_PARAMS_CHANGED
      * |-------|-------|-------|-------|
      */
 
@@ -2513,7 +2510,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      */
     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
 
-
     /* End of masks for mPrivateFlags3 */
 
     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
@@ -2652,19 +2648,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     private static final int PFLAG3_POINTER_ICON_VALUE_START = 3 << PFLAG3_POINTER_ICON_LSHIFT;
 
     /**
-     * Flag indicating that this view has requested a partial layout and
-     * is added to the AttachInfo's list of views that need a partial layout
-     * request handled on the next traversal.
-     */
-    static final int PFLAG3_PARTIAL_LAYOUT_REQUESTED = 0x800000;
-
-    /**
-     * Flag indicating that this view's LayoutParams have been explicitly changed
-     * since the last layout pass.
-     */
-    static final int PFLAG3_LAYOUT_PARAMS_CHANGED = 0x1000000;
-
-    /**
      * Always allow a user to over-scroll this view, provided it is a
      * view that can scroll.
      *
@@ -12671,14 +12654,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * ViewGroup.LayoutParams, and these correspond to the different subclasses
      * of ViewGroup that are responsible for arranging their children.
      *
-     * <p>This method may return null if this View is not attached to a parent
+     * This method may return null if this View is not attached to a parent
      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
      * was not invoked successfully. When a View is attached to a parent
-     * ViewGroup, this method must not return null.</p>
-     *
-     * <p>Callers that modify the returned LayoutParams object should call
-     * {@link #setLayoutParams(LayoutParams)} to explicitly inform the view that
-     * LayoutParams have changed.</p>
+     * ViewGroup, this method must not return null.
      *
      * @return The LayoutParams associated with this view, or null if no
      *         parameters have been set yet
@@ -12695,9 +12674,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * correspond to the different subclasses of ViewGroup that are responsible
      * for arranging their children.
      *
-     * <p>If the View's existing LayoutParams object as obtained by {@link #getLayoutParams()} is
-     * modified, you should call this method to inform the view that it has changed.</p>
-     *
      * @param params The layout parameters for this view, cannot be null
      */
     public void setLayoutParams(ViewGroup.LayoutParams params) {
@@ -12705,7 +12681,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
             throw new NullPointerException("Layout parameters cannot be null");
         }
         mLayoutParams = params;
-        mPrivateFlags3 |= PFLAG3_LAYOUT_PARAMS_CHANGED;
         resolveLayoutParams();
         if (mParent instanceof ViewGroup) {
             ((ViewGroup) mParent).onSetLayoutParams(this, params);
@@ -14381,12 +14356,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
             mParent.requestTransparentRegion(this);
         }
 
-        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
-            initialAwakenScrollBars();
-            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
-        }
-
-        mPrivateFlags3 &= ~(PFLAG3_IS_LAID_OUT | PFLAG3_PARTIAL_LAYOUT_REQUESTED);
+        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
 
         jumpDrawablesToCurrentState();
 
@@ -14724,13 +14694,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      */
     @CallSuper
     protected void onDetachedFromWindowInternal() {
-        if (mAttachInfo != null && isPartialLayoutRequested()) {
-            mAttachInfo.mPartialLayoutViews.remove(this);
-        }
-
         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
-        mPrivateFlags3 &= ~(PFLAG3_IS_LAID_OUT | PFLAG3_PARTIAL_LAYOUT_REQUESTED
-                | PFLAG3_LAYOUT_PARAMS_CHANGED);
+        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
 
         removeUnsetPressCallback();
         removeLongPressCallback();
@@ -16917,32 +16882,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Indicates whether or not this view has requested a partial layout that
-     * may not affect its size or position within its parent. This state will be reset
-     * the next time this view is laid out.
-     *
-     * @return true if partial layout has been requested
-     */
-    public final boolean isPartialLayoutRequested() {
-        return (mPrivateFlags3 & PFLAG3_PARTIAL_LAYOUT_REQUESTED)
-                == PFLAG3_PARTIAL_LAYOUT_REQUESTED;
-    }
-
-    /**
-     * Returns true if this view's {@link ViewGroup.LayoutParams LayoutParams} changed
-     * since the last time this view was successfully laid out. Typically this happens as a
-     * result of a call to {@link #setLayoutParams(LayoutParams)}.
-     *
-     * @return true if this view's LayoutParams changed since last layout.
-     */
-    public final boolean didLayoutParamsChange() {
-        if (sLayoutParamsAlwaysChanged) {
-            return true;
-        }
-        return (mPrivateFlags3 & PFLAG3_LAYOUT_PARAMS_CHANGED) == PFLAG3_LAYOUT_PARAMS_CHANGED;
-    }
-
-    /**
      * Return true if o is a ViewGroup that is laying out using optical bounds.
      * @hide
      */
@@ -16999,7 +16938,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
             onLayout(changed, l, t, r, b);
             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
-            mPrivateFlags3 &= ~PFLAG3_LAYOUT_PARAMS_CHANGED;
 
             ListenerInfo li = mListenerInfo;
             if (li != null && li.mOnLayoutChangeListeners != null) {
@@ -17013,7 +16951,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         }
 
         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
-        mPrivateFlags3 &= ~PFLAG3_PARTIAL_LAYOUT_REQUESTED;
         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
     }
 
@@ -19111,7 +19048,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         mPrivateFlags |= PFLAG_INVALIDATED;
 
         if (mParent != null && !mParent.isLayoutRequested()) {
-            mParent.requestLayoutForChild(this);
+            mParent.requestLayout();
         }
         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
             mAttachInfo.mViewRequestingLayout = null;
@@ -19130,11 +19067,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         mPrivateFlags |= PFLAG_INVALIDATED;
     }
 
-    void forcePartialLayout() {
-        forceLayout();
-        mPrivateFlags3 |= PFLAG3_PARTIAL_LAYOUT_REQUESTED;
-    }
-
     /**
      * <p>
      * This is called to find out how big a view should be. The parent
@@ -22021,7 +21953,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         interface Callbacks {
             void playSoundEffect(int effectId);
             boolean performHapticFeedback(int effectId, boolean always);
-            void schedulePartialLayout();
         }
 
         /**
index 488063b..0f7d296 100644 (file)
@@ -60,8 +60,6 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
 /**
  * <p>
@@ -5531,172 +5529,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             int l, int t, int r, int b);
 
     /**
-     * {@inheritDoc}
-     *
-     * <p>Most subclasses should not need to override this method. The default implementation
-     * will call {@link #findDependentLayoutAxes(View, int)} to determine how
-     * to optimally proceed. If neither horizontal nor vertical layout depends on the given
-     * child, this method will call {@link #requestPartialLayoutForChild(View)}. If one or both
-     * do, it will call {@link #requestLayout()}.</p>
-     *
-     * @param child Child requesting a layout
-     */
-    @Override
-    public void requestLayoutForChild(View child) {
-        if (child == null || child.getParent() != this) {
-            throw new IllegalArgumentException(
-                    "child parameter must be a direct child view of this ViewGroup");
-        }
-
-        // If we don't have a parent ourselves, record that we need a full layout.
-        // Our whole subtree is detached.
-        final ViewParent parent = getParent();
-        if (parent == null) {
-            requestLayout();
-            return;
-        }
-
-        // We can optimize the layout request for this child into a partial layout
-        // if the child has already been laid out at least once and neither horizontal nor
-        // vertical layout within ourselves is dependent on pending layout changes within
-        // this child. Otherwise we need to request a full layout for ourselves and continue
-        // to recurse up the view hierarchy.
-        if (child.isLaidOut() && findDependentLayoutAxes(child, FLAG_LAYOUT_AXIS_ANY) == 0) {
-            requestPartialLayoutForChild(child);
-        } else {
-            requestLayout();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * <p>The default implementation returns {@link #FLAG_LAYOUT_AXIS_ANY}.
-     * Optimized implementations for specific ViewGroup subclasses may check if the child's
-     * {@link View#didLayoutParamsChange() LayoutParams changed} and in what ways.</p>
-     *
-     * @param child Direct child of this ViewParent to check
-     * @param axisFilter Which axes to check for dependencies. Can be
-     *                   {@link #FLAG_LAYOUT_AXIS_HORIZONTAL}, {@link #FLAG_LAYOUT_AXIS_VERTICAL}
-     *                   or {@link #FLAG_LAYOUT_AXIS_ANY}.
-     * @return Axes of this ViewParent that depend on the given child's layout changes
-     */
-    @Override
-    public int findDependentLayoutAxes(View child, int axisFilter) {
-        return FLAG_LAYOUT_AXIS_ANY;
-    }
-
-    /**
-     * This is a helper implementation for {@link #findDependentLayoutAxes(View, int)} that
-     * is not the default implementation in ViewGroup. This is to preserve compatibility with
-     * existing app-side ViewGroup subclasses that existed before the partial layout system was
-     * added to Android. It explicitly checks that the LayoutParams of the child are of the
-     * expected type so that subclasses of standard framework layouts do not erroneously
-     * start believing that it's safe to do a partial layout when that assertion can't
-     * reasonably be confirmed.
-     *
-     * <p>If you're reading this as an author of a custom ViewGroup's findDependentLayoutAxes
-     * method you might be frustrated to discover that it is not a part of the Android public API.
-     * Many ViewGroup implementations will need to make small but important modifications
-     * to an implementation like this one in order to be correct. Instead of encouraging
-     * view authors to call this method, then make their own redundant recursive calls to
-     * <code>getParent().findDependentLayoutAxes(...)</code> in addition to the one
-     * that can happen here, this method is hidden and only used internally.</p>
-     *
-     * <p>Do feel free to copy this implementation and adapt it to suit your own purposes.</p>
-     *
-     * @hide
-     */
-    protected final int findDependentLayoutAxesHelper(View child, int axisFilter,
-            Class<?> layoutParamsClass) {
-        if (!checkPartialLayoutParams(child, layoutParamsClass)) return axisFilter;
-        if (child.didLayoutParamsChange()) {
-            // Anything could have changed about our previous assumptions.
-            return axisFilter;
-        }
-
-        final LayoutParams lp = child.getLayoutParams();
-
-        // Our layout can always end up depending on a WRAP_CONTENT child.
-        final int wrapAxisFilter = ((lp.width == WRAP_CONTENT ? FLAG_LAYOUT_AXIS_HORIZONTAL : 0)
-                | (lp.height == WRAP_CONTENT ? FLAG_LAYOUT_AXIS_VERTICAL : 0)) & axisFilter;
-
-        if (wrapAxisFilter == axisFilter) {
-            // We know all queried axes are affected, just return early.
-            return wrapAxisFilter;
-        }
-
-        // Our layout *may* depend on a MATCH_PARENT child, depending on whether we can determine
-        // that our layout will remain stable within our parent. We need to ask.
-        final int matchAxisFilter = ((lp.width == MATCH_PARENT ? FLAG_LAYOUT_AXIS_HORIZONTAL : 0)
-                | (lp.height == MATCH_PARENT ? FLAG_LAYOUT_AXIS_VERTICAL : 0)) & axisFilter;
-
-        if (matchAxisFilter != 0 || wrapAxisFilter != 0) {
-            final ViewParent parent = getParent();
-            if (parent != null) {
-                // If our parent depends on us for an axis, then our layout can also be affected
-                // by a MATCH_PARENT child along that axis.
-                return getParent().findDependentLayoutAxes(this, matchAxisFilter)
-                        | wrapAxisFilter;
-            }
-
-            // If we don't have a parent, assume we're affected
-            // in any determined affected direction.
-            return matchAxisFilter | wrapAxisFilter;
-        }
-
-        // Two exact sizes and LayoutParams didn't change. We're safe.
-        return 0;
-    }
-
-    /**
-     * Throw an IllegalArgumentException if the supplied view is not a direct child of
-     * this ViewGroup and return false if this view's LayoutParams is not of class lpClass.
-     * Implementations of {@link ViewGroup#findDependentLayoutAxes(View, int)} use this
-     * to check input parameters and defensively return the full axis filter mask themselves
-     * if the LayoutParams class is not of the exact expected type; e.g. it is a subclass
-     * of one of the standard framework layouts and we can't make assumptions.
-     * @hide
-     */
-    protected final boolean checkPartialLayoutParams(View child, Class<?> lpClass) {
-        if (child.getParent() != this) {
-            throw new IllegalArgumentException("View " + child
-                    + " is not a direct child of " + this);
-        }
-        final ViewGroup.LayoutParams lp = child.getLayoutParams();
-        return lp != null || lp.getClass() == lpClass;
-    }
-
-    /**
-     * Called when a child of this ViewParent requires a relayout before the next frame
-     * is drawn, but the caller can guarantee that the size of the child will not change
-     * during a measure and layout pass.
-     *
-     * <p>A call to this method will schedule a partial layout for the supplied view as long as
-     * it is a direct child of this ViewGroup and this ViewGroup is attached to a window.
-     * On the next scheduled view hierarchy traversal the given child view will be re-measured
-     * at its current measured size and re-laid out at its current position within its parent.</p>
-     *
-     * @param child Child that requires a partial layout
-     */
-    public void requestPartialLayoutForChild(View child) {
-        if (!child.isPartialLayoutRequested()) {
-            child.forcePartialLayout();
-            if (mAttachInfo != null) {
-                final List<View> partialLayoutViews = mAttachInfo.mPartialLayoutViews;
-                final boolean schedule = partialLayoutViews.isEmpty();
-                partialLayoutViews.add(child);
-                if (schedule) {
-                    mAttachInfo.mRootCallbacks.schedulePartialLayout();
-                }
-                child.invalidate();
-            } else {
-                requestLayout();
-            }
-        }
-    }
-
-    /**
      * Indicates whether the view group has the ability to animate its children
      * after the first layout.
      *
@@ -6042,7 +5874,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
      *         of its descendants
      */
     protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
-        return new LayoutParams(p);
+        return p;
     }
 
     /**
index f2ab35e..e9b123b 100644 (file)
@@ -26,11 +26,6 @@ import android.view.accessibility.AccessibilityEvent;
  * 
  */
 public interface ViewParent {
-    public static final int FLAG_LAYOUT_AXIS_HORIZONTAL = 1;
-    public static final int FLAG_LAYOUT_AXIS_VERTICAL = 2;
-    public static final int FLAG_LAYOUT_AXIS_ANY
-            = FLAG_LAYOUT_AXIS_HORIZONTAL | FLAG_LAYOUT_AXIS_VERTICAL;
-
     /**
      * Called when something has changed which has invalidated the layout of a
      * child of this view parent. This will schedule a layout pass of the view
@@ -618,48 +613,4 @@ public interface ViewParent {
      * @return true if the action was consumed by this ViewParent
      */
     public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle arguments);
-
-    /**
-     * Called when a child of this ViewParent requires a relayout before
-     * the next frame is drawn. A call to {@link View#requestLayout() child.requestLayout()}
-     * will implicitly result in a call to
-     * <code>child.getParent().requestLayoutForChild(child)</code>. App code should not call this
-     * method directly. Call <code>child.requestLayout()</code> instead.
-     *
-     * <p>On versions of Android from API 23 and older, a call to {@link View#requestLayout()}
-     * would cause a matching call to <code>requestLayout</code> on each parent view up to
-     * the root. With the addition of <code>requestLayoutForChild</code> a view's parent may
-     * explicitly decide how to handle a layout request. This allows for optimizations when
-     * a view parent knows that a layout-altering change in a child will not affect its own
-     * measurement.</p>
-     *
-     * @param child Child requesting a layout
-     */
-    public void requestLayoutForChild(View child);
-
-    /**
-     * Determine which axes of this ViewParent's layout are dependent on the given
-     * direct child view. The returned value is a flag set that may contain
-     * {@link #FLAG_LAYOUT_AXIS_HORIZONTAL} and/or {@link #FLAG_LAYOUT_AXIS_VERTICAL}.
-     * {@link #FLAG_LAYOUT_AXIS_ANY} is provided as a shortcut for
-     * <code>FLAG_LAYOUT_AXIS_HORIZONTAL | FLAG_LAYOUT_AXIS_VERTICAL</code>.
-     *
-     * <p>The given child must be a direct child view. Implementations should throw
-     * {@link IllegalArgumentException} otherwise.</p>
-     *
-     * <p>The caller may specify which axes it cares about. This should be treated as a filter.
-     * Implementations should never return a result that would be different from
-     * <code>result & axisFilter</code>.</p>
-     *
-     * @param child Direct child of this ViewParent to check
-     * @param axisFilter Which axes to check for dependencies. Can be
-     *                   {@link #FLAG_LAYOUT_AXIS_HORIZONTAL}, {@link #FLAG_LAYOUT_AXIS_VERTICAL}
-     *                   or {@link #FLAG_LAYOUT_AXIS_ANY}.
-     * @return Axes of this ViewParent that depend on the given child's layout changes
-     *
-     * @see #FLAG_LAYOUT_AXIS_HORIZONTAL
-     * @see #FLAG_LAYOUT_AXIS_VERTICAL
-     * @see #FLAG_LAYOUT_AXIS_ANY
-     */
-    public int findDependentLayoutAxes(View child, int axisFilter);
 }
index b7bb9a3..12cf66e 100644 (file)
@@ -91,7 +91,6 @@ import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.concurrent.CountDownLatch;
 import java.util.HashSet;
-import java.util.List;
 
 /**
  * The top of a view hierarchy, implementing the needed protocol between View
@@ -953,25 +952,6 @@ public final class ViewRootImpl implements ViewParent,
     }
 
     @Override
-    public void requestLayoutForChild(View child) {
-        requestLayout();
-    }
-
-    @Override
-    public int findDependentLayoutAxes(View child, int axisFilter) {
-        if (child != mView) {
-            return 0;
-        }
-
-        final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) child.getLayoutParams();
-        final int horizontal = (lp.width == WindowManager.LayoutParams.WRAP_CONTENT
-                || lp.horizontalWeight != 0) ? FLAG_LAYOUT_AXIS_HORIZONTAL : 0;
-        final int vertical = (lp.height == WindowManager.LayoutParams.WRAP_CONTENT
-                || lp.verticalWeight != 0) ? FLAG_LAYOUT_AXIS_VERTICAL : 0;
-        return (horizontal | vertical) & axisFilter;
-    }
-
-    @Override
     public boolean isLayoutRequested() {
         return mLayoutRequested;
     }
@@ -1115,10 +1095,6 @@ public final class ViewRootImpl implements ViewParent,
         }
     }
 
-    public void schedulePartialLayout() {
-        scheduleTraversals();
-    }
-
     /**
      * Notifies the HardwareRenderer that a new frame will be coming soon.
      * Currently only {@link ThreadedRenderer} cares about this, and uses
@@ -1958,60 +1934,7 @@ public final class ViewRootImpl implements ViewParent,
                 || mAttachInfo.mRecomputeGlobalAttributes;
         if (didLayout) {
             performLayout(lp, desiredWindowWidth, desiredWindowHeight);
-        }
-
-        /*
-         * Handle partial layouts.
-         *
-         * Views that have requested partial layouts will not change size or position
-         * within their parent view, therefore we will re-measure and re-layout each one
-         * after any regularly scheduled layout pass. Any view that already had its
-         * isLayoutRequested bit cleared will be skipped, since this means the view has already
-         * been measured and laid out on this traversal pass naturally. Views won't be added
-         * to this list if layout was already requested when a partial layout is requested
-         * for a view, so there should not be duplicates in the list.
-         */
-        final List<View> partialLayoutViews = mAttachInfo.mPartialLayoutViews;
-        final boolean didPartialLayout;
-        if (!partialLayoutViews.isEmpty()) {
-            // Measurement or layout of views may result in changes to the list
-            // of partial-layout views. Swap in an "empty" list to prevent
-            // concurrent modification of the list being traversed.
-            if (mAttachInfo.mEmptyPartialLayoutViews == null) {
-                mAttachInfo.mPartialLayoutViews = new ArrayList<>();
-            } else {
-                mAttachInfo.mPartialLayoutViews = mAttachInfo.mEmptyPartialLayoutViews;
-            }
-
-            final int count = partialLayoutViews.size();
-            mInLayout = true;
-            for (int i = 0; i < count; i++) {
-                final View view = partialLayoutViews.get(i);
-
-                // Make sure the view is still attached and that it still has layout requested.
-                // We might have already serviced the layout request through the standard full-tree
-                // layout pass above or even through a previous partial layout view in this list.
-                if (view.isAttachedToWindow() && view.isLayoutRequested()) {
-                    final int widthSpec = MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(),
-                            MeasureSpec.EXACTLY);
-                    final int heightSpec = MeasureSpec.makeMeasureSpec(view.getMeasuredHeight(),
-                            MeasureSpec.EXACTLY);
-                    view.measure(widthSpec, heightSpec);
-                    view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
-                }
-            }
-            mInLayout = false;
-            didPartialLayout = true;
-            triggerGlobalLayoutListener = true;
-
-            // The traversal list becomes the new empty list.
-            partialLayoutViews.clear();
-            mAttachInfo.mEmptyPartialLayoutViews = partialLayoutViews;
-        } else {
-            didPartialLayout = false;
-        }
 
-        if (didLayout || didPartialLayout) {
             // By this point all views have been sized and positioned
             // We can compute the transparent area
 
@@ -2041,7 +1964,7 @@ public final class ViewRootImpl implements ViewParent,
 
             if (DBG) {
                 System.out.println("======================================");
-                System.out.println("performTraversals -- after performLayout/partial layout");
+                System.out.println("performTraversals -- after setFrame");
                 host.debug();
             }
         }
index f050e49..e1ce9fe 100644 (file)
@@ -2109,11 +2109,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     }
 
     @Override
-    public int findDependentLayoutAxes(View child, int axisFilter) {
-        return findDependentLayoutAxesHelper(child, axisFilter, LayoutParams.class);
-    }
-
-    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         if (mSelector == null) {
             useDefaultSelector();
index 4d9f55c..280ff15 100644 (file)
@@ -21,8 +21,12 @@ import java.util.ArrayList;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.Gravity;
@@ -32,6 +36,9 @@ import android.view.ViewGroup;
 import android.view.ViewHierarchyEncoder;
 import android.widget.RemoteViews.RemoteView;
 
+import com.android.internal.R;
+
+
 /**
  * FrameLayout is designed to block out an area on the screen to display
  * a single item. Generally, FrameLayout should be used to hold a single child view, because it can
@@ -164,10 +171,6 @@ public class FrameLayout extends ViewGroup {
             mPaddingBottom + mForegroundPaddingBottom;
     }
 
-    @Override
-    public int findDependentLayoutAxes(View child, int axisFilter) {
-        return findDependentLayoutAxesHelper(child, axisFilter, LayoutParams.class);
-    }
 
     /**
      * {@inheritDoc}
index bdb1e83..ad939be 100644 (file)
@@ -16,7 +16,6 @@
 
 package android.widget;
 
-import android.view.ViewParent;
 import com.android.internal.R;
 
 import android.annotation.IntDef;
@@ -38,8 +37,6 @@ import android.widget.RemoteViews.RemoteView;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
 /**
  * A Layout that arranges its children in a single column or a single row. The direction of 
@@ -647,60 +644,6 @@ public class LinearLayout extends ViewGroup {
         }
     }
 
-    @Override
-    public int findDependentLayoutAxes(View child, int axisFilter) {
-        // This implementation is almost exactly equivalent to the default implementation
-        // offered to the rest of the framework in ViewGroup, but we treat weight to be
-        // functionally equivalent to MATCH_PARENT along the orientation axis.
-
-        if (!checkPartialLayoutParams(child, LayoutParams.class)) return axisFilter;
-        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-        if (child.didLayoutParamsChange()) {
-            // Anything could have changed about our previous assumptions.
-            return axisFilter;
-        }
-
-        // Our layout can always end up depending on a WRAP_CONTENT child.
-        final int wrapAxisFilter = ((lp.width == WRAP_CONTENT ? FLAG_LAYOUT_AXIS_HORIZONTAL : 0)
-                | (lp.height == WRAP_CONTENT ? FLAG_LAYOUT_AXIS_VERTICAL : 0)) & axisFilter;
-
-        if (wrapAxisFilter == axisFilter) {
-            // We know all queried axes are affected, just return early.
-            return wrapAxisFilter;
-        }
-
-        // Our layout *may* depend on a MATCH_PARENT child, depending on whether we can determine
-        // that our layout will remain stable within our parent. We need to ask.
-        int matchAxisFilter = ((lp.width == MATCH_PARENT ? FLAG_LAYOUT_AXIS_HORIZONTAL : 0)
-                | (lp.height == MATCH_PARENT ? FLAG_LAYOUT_AXIS_VERTICAL : 0)) & axisFilter;
-
-        // For LinearLayout, a nonzero weight is equivalent to MATCH_PARENT for this purpose.
-        if (lp.weight > 0) {
-            if (mOrientation == HORIZONTAL) {
-                matchAxisFilter |= FLAG_LAYOUT_AXIS_HORIZONTAL & axisFilter;
-            } else {
-                matchAxisFilter |= FLAG_LAYOUT_AXIS_VERTICAL & axisFilter;
-            }
-        }
-
-        if (matchAxisFilter != 0 || wrapAxisFilter != 0) {
-            final ViewParent parent = getParent();
-            if (parent != null) {
-                // If our parent depends on us for an axis, then our layout can also be affected
-                // by a MATCH_PARENT child along that axis.
-                return getParent().findDependentLayoutAxes(this, matchAxisFilter)
-                        | wrapAxisFilter;
-            }
-
-            // If we don't have a parent, assume we're affected
-            // in any determined affected direction.
-            return matchAxisFilter | wrapAxisFilter;
-        }
-
-        // Two exact sizes and LayoutParams didn't change. We're safe.
-        return 0;
-    }
-
     /**
      * Determines where to position dividers between children.
      *
index b43ea76..53ca6d1 100644 (file)
@@ -1158,7 +1158,7 @@ public class ListView extends AbsListView {
             final View child = obtainView(0, mIsScrap);
 
             // Lay out child directly against the parent measure spec so that
-            // we can obtain expected minimum width and height.
+            // we can obtain exected minimum width and height.
             measureScrapChild(child, 0, widthMeasureSpec, heightSize);
 
             childWidth = child.getMeasuredWidth();
index 56513a3..94b75b7 100644 (file)
@@ -6814,11 +6814,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
 
         if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
             if (!compressText(ellipsisWidth)) {
+                final int height = mLayoutParams.height;
                 // If the size of the view does not depend on the size of the text, try to
                 // start the marquee immediately
-                final ViewParent parent = getParent();
-                if (parent != null && parent.findDependentLayoutAxes(this,
-                        ViewParent.FLAG_LAYOUT_AXIS_VERTICAL) == 0) {
+                if (height != LayoutParams.WRAP_CONTENT && height != LayoutParams.MATCH_PARENT) {
                     startMarquee();
                 } else {
                     // Defer the start of the marquee until we know our width (see setFrame())
@@ -7217,9 +7216,37 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
      * new view layout.
      */
     private void checkForResize() {
-        // Always request a layout. The parent will perform the correct version
-        // of the intended optimizations as part of requestLayoutForChild.
-        requestLayout();
+        boolean sizeChanged = false;
+
+        if (mLayout != null) {
+            // Check if our width changed
+            if (mLayoutParams.width == LayoutParams.WRAP_CONTENT) {
+                sizeChanged = true;
+                invalidate();
+            }
+
+            // Check if our height changed
+            if (mLayoutParams.height == LayoutParams.WRAP_CONTENT) {
+                int desiredHeight = getDesiredHeight();
+
+                if (desiredHeight != this.getHeight()) {
+                    sizeChanged = true;
+                }
+            } else if (mLayoutParams.height == LayoutParams.MATCH_PARENT) {
+                if (mDesiredHeightAtMeasure >= 0) {
+                    int desiredHeight = getDesiredHeight();
+
+                    if (desiredHeight != mDesiredHeightAtMeasure) {
+                        sizeChanged = true;
+                    }
+                }
+            }
+        }
+
+        if (sizeChanged) {
+            requestLayout();
+            // caller will have already invalidated
+        }
     }
 
     /**
@@ -7227,11 +7254,56 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
      * or merely a new text layout.
      */
     private void checkForRelayout() {
-        // Always request a layout. The parent will perform the correct version
-        // of the intended optimizations as part of requestLayoutForChild.
-        nullLayouts();
-        requestLayout();
-        invalidate();
+        // If we have a fixed width, we can just swap in a new text layout
+        // if the text height stays the same or if the view height is fixed.
+
+        if ((mLayoutParams.width != LayoutParams.WRAP_CONTENT ||
+                (mMaxWidthMode == mMinWidthMode && mMaxWidth == mMinWidth)) &&
+                (mHint == null || mHintLayout != null) &&
+                (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight() > 0)) {
+            // Static width, so try making a new text layout.
+
+            int oldht = mLayout.getHeight();
+            int want = mLayout.getWidth();
+            int hintWant = mHintLayout == null ? 0 : mHintLayout.getWidth();
+
+            /*
+             * No need to bring the text into view, since the size is not
+             * changing (unless we do the requestLayout(), in which case it
+             * will happen at measure).
+             */
+            makeNewLayout(want, hintWant, UNKNOWN_BORING, UNKNOWN_BORING,
+                          mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(),
+                          false);
+
+            if (mEllipsize != TextUtils.TruncateAt.MARQUEE) {
+                // In a fixed-height view, so use our new text layout.
+                if (mLayoutParams.height != LayoutParams.WRAP_CONTENT &&
+                    mLayoutParams.height != LayoutParams.MATCH_PARENT) {
+                    invalidate();
+                    return;
+                }
+
+                // Dynamic height, but height has stayed the same,
+                // so use our new text layout.
+                if (mLayout.getHeight() == oldht &&
+                    (mHintLayout == null || mHintLayout.getHeight() == oldht)) {
+                    invalidate();
+                    return;
+                }
+            }
+
+            // We lose: the height has changed and we have a dynamic height.
+            // Request a new view layout using our new text layout.
+            requestLayout();
+            invalidate();
+        } else {
+            // Dynamic width, so we have no choice but to request a new
+            // view layout with a new text layout.
+            nullLayouts();
+            requestLayout();
+            invalidate();
+        }
     }
 
     @Override
index 6e56513..acbf5eb 100644 (file)
@@ -1368,11 +1368,6 @@ public class Toolbar extends ViewGroup {
     }
 
     @Override
-    public int findDependentLayoutAxes(View child, int axisFilter) {
-        return findDependentLayoutAxesHelper(child, axisFilter, LayoutParams.class);
-    }
-
-    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int width = 0;
         int height = 0;
index 3e65320..c3a7460 100644 (file)
@@ -360,11 +360,6 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar
     }
 
     @Override
-    public int findDependentLayoutAxes(View child, int axisFilter) {
-        return findDependentLayoutAxesHelper(child, axisFilter, LayoutParams.class);
-    }
-
-    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         pullChildren();