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);
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();
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);
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();
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);
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 {
}
}
+
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);
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();
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);
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();
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);
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 {
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);
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();
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);
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();
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);
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 {
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;
* 1 PFLAG3_SCROLL_INDICATOR_END
* 1 PFLAG3_ASSIST_BLOCKED
* 1111111 PFLAG3_POINTER_ICON_MASK
- * 1 PFLAG3_PARTIAL_LAYOUT_REQUESTED
- * 1 PFLAG3_LAYOUT_PARAMS_CHANGED
* |-------|-------|-------|-------|
*/
*/
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;
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.
*
* 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
* 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) {
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);
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();
*/
@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();
}
/**
- * 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
*/
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) {
}
mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
- mPrivateFlags3 &= ~PFLAG3_PARTIAL_LAYOUT_REQUESTED;
mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
}
mPrivateFlags |= PFLAG_INVALIDATED;
if (mParent != null && !mParent.isLayoutRequested()) {
- mParent.requestLayoutForChild(this);
+ mParent.requestLayout();
}
if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
mAttachInfo.mViewRequestingLayout = null;
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
interface Callbacks {
void playSoundEffect(int effectId);
boolean performHapticFeedback(int effectId, boolean always);
- void schedulePartialLayout();
}
/**
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>
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.
*
* of its descendants
*/
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
+ return p;
}
/**
*
*/
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
* @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);
}
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
}
@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;
}
}
}
- public void schedulePartialLayout() {
- scheduleTraversals();
- }
-
/**
* Notifies the HardwareRenderer that a new frame will be coming soon.
* Currently only {@link ThreadedRenderer} cares about this, and uses
|| 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
if (DBG) {
System.out.println("======================================");
- System.out.println("performTraversals -- after performLayout/partial layout");
+ System.out.println("performTraversals -- after setFrame");
host.debug();
}
}
}
@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();
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;
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
mPaddingBottom + mForegroundPaddingBottom;
}
- @Override
- public int findDependentLayoutAxes(View child, int axisFilter) {
- return findDependentLayoutAxesHelper(child, axisFilter, LayoutParams.class);
- }
/**
* {@inheritDoc}
package android.widget;
-import android.view.ViewParent;
import com.android.internal.R;
import android.annotation.IntDef;
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
}
}
- @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.
*
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();
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())
* 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
+ }
}
/**
* 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
}
@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;
}
@Override
- public int findDependentLayoutAxes(View child, int axisFilter) {
- return findDependentLayoutAxesHelper(child, axisFilter, LayoutParams.class);
- }
-
- @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
pullChildren();