summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt5
-rw-r--r--api/system-current.txt5
-rw-r--r--core/java/android/view/ViewGroup.java187
3 files changed, 197 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt
index 5f4d6e98044c..4375e6f4ff0e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -36560,6 +36560,7 @@ package android.view {
ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int);
ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int, int);
method public boolean addStatesFromChildren();
+ method public void addTransientView(android.view.View, int);
method public void addView(android.view.View);
method public void addView(android.view.View, int);
method public void addView(android.view.View, int, int);
@@ -36611,6 +36612,9 @@ package android.view {
method public int getNestedScrollAxes();
method public int getPersistentDrawingCache();
method public boolean getTouchscreenBlocksFocus();
+ method public android.view.View getTransientView(int);
+ method public int getTransientViewCount();
+ method public int getTransientViewIndex(int);
method public int indexOfChild(android.view.View);
method public final void invalidateChild(android.view.View, android.graphics.Rect);
method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
@@ -36644,6 +36648,7 @@ package android.view {
method public void removeAllViews();
method public void removeAllViewsInLayout();
method protected void removeDetachedView(android.view.View, boolean);
+ method public void removeTransientView(android.view.View);
method public void removeView(android.view.View);
method public void removeViewAt(int);
method public void removeViewInLayout(android.view.View);
diff --git a/api/system-current.txt b/api/system-current.txt
index e44ee6ec44ac..363967373791 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -38762,6 +38762,7 @@ package android.view {
ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int);
ctor public ViewGroup(android.content.Context, android.util.AttributeSet, int, int);
method public boolean addStatesFromChildren();
+ method public void addTransientView(android.view.View, int);
method public void addView(android.view.View);
method public void addView(android.view.View, int);
method public void addView(android.view.View, int, int);
@@ -38813,6 +38814,9 @@ package android.view {
method public int getNestedScrollAxes();
method public int getPersistentDrawingCache();
method public boolean getTouchscreenBlocksFocus();
+ method public android.view.View getTransientView(int);
+ method public int getTransientViewCount();
+ method public int getTransientViewIndex(int);
method public int indexOfChild(android.view.View);
method public final void invalidateChild(android.view.View, android.graphics.Rect);
method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
@@ -38846,6 +38850,7 @@ package android.view {
method public void removeAllViews();
method public void removeAllViewsInLayout();
method protected void removeDetachedView(android.view.View, boolean);
+ method public void removeTransientView(android.view.View);
method public void removeView(android.view.View);
method public void removeViewAt(int);
method public void removeViewInLayout(android.view.View);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 10724b0919ef..afc0eeef91eb 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -494,6 +494,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
private int mNestedScrollAxes;
+ // Used to manage the list of transient views, added by addTransientView()
+ private List<Integer> mTransientIndices = null;
+ private List<View> mTransientViews = null;
+
+
/**
* Empty ActionMode used as a sentinel in recursive entries to startActionModeForChild.
*
@@ -2822,6 +2827,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
child.dispatchAttachedToWindow(info,
visibility | (child.mViewFlags & VISIBILITY_MASK));
}
+ final int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
+ for (int i = 0; i < transientCount; ++i) {
+ View view = mTransientViews.get(i);
+ view.dispatchAttachedToWindow(info, visibility | (view.mViewFlags & VISIBILITY_MASK));
+ }
}
@Override
@@ -2991,6 +3001,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
children[i].dispatchDetachedFromWindow();
}
clearDisappearingChildren();
+ final int transientCount = mTransientViews == null ? 0 : mTransientIndices.size();
+ for (int i = 0; i < transientCount; ++i) {
+ View view = mTransientViews.get(i);
+ view.dispatchDetachedFromWindow();
+ }
super.dispatchDetachedFromWindow();
}
@@ -3291,6 +3306,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final long drawingTime = getDrawingTime();
if (usingRenderNodeProperties) canvas.insertReorderBarrier();
+ final int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
+ int transientIndex = transientCount != 0 ? 0 : -1;
// Only use the preordered list if not HW accelerated, since the HW pipeline will do the
// draw reordering internally
final ArrayList<View> preorderedList = usingRenderNodeProperties
@@ -3298,6 +3315,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final boolean customOrder = preorderedList == null
&& isChildrenDrawingOrderEnabled();
for (int i = 0; i < childrenCount; i++) {
+ while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) {
+ final View transientChild = mTransientViews.get(transientIndex);
+ if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
+ transientChild.getAnimation() != null) {
+ more |= drawChild(canvas, transientChild, drawingTime);
+ }
+ transientIndex++;
+ if (transientIndex >= transientCount) {
+ transientIndex = -1;
+ }
+ }
int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
final View child = (preorderedList == null)
? children[childIndex] : preorderedList.get(childIndex);
@@ -3305,6 +3333,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
more |= drawChild(canvas, child, drawingTime);
}
}
+ while (transientIndex >= 0) {
+ // there may be additional transient views after the normal views
+ final View transientChild = mTransientViews.get(transientIndex);
+ if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
+ transientChild.getAnimation() != null) {
+ more |= drawChild(canvas, transientChild, drawingTime);
+ }
+ transientIndex++;
+ if (transientIndex >= transientCount) {
+ break;
+ }
+ }
if (preorderedList != null) preorderedList.clear();
// Draw any disappearing views that have animations
@@ -3785,6 +3825,135 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
/**
+ * This method adds a view to this container at the specified index purely for the
+ * purposes of allowing that view to draw even though it is not a normal child of
+ * the container. That is, the view does not participate in layout, focus, accessibility,
+ * input, or other normal view operations; it is purely an item to be drawn during the normal
+ * rendering operation of this container. The index that it is added at is the order
+ * in which it will be drawn, with respect to the other views in the container.
+ * For example, a transient view added at index 0 will be drawn before all other views
+ * in the container because it will be drawn first (including before any real view
+ * at index 0). There can be more than one transient view at any particular index;
+ * these views will be drawn in the order in which they were added to the list of
+ * transient views. The index of transient views can also be greater than the number
+ * of normal views in the container; that just means that they will be drawn after all
+ * other views are drawn.
+ *
+ * <p>Note that since transient views do not participate in layout, they must be sized
+ * manually or, more typically, they should just use the size that they had before they
+ * were removed from their container.</p>
+ *
+ * <p>Transient views are useful for handling animations of views that have been removed
+ * from the container, but which should be animated out after the removal. Adding these
+ * views as transient views allows them to participate in drawing without side-effecting
+ * the layout of the container.</p>
+ *
+ * <p>Transient views must always be explicitly {@link #removeTransientView(View) removed}
+ * from the container when they are no longer needed. For example, a transient view
+ * which is added in order to fade it out in its old location should be removed
+ * once the animation is complete.</p>
+ *
+ * @param view The view to be added
+ * @param index The index at which this view should be drawn, must be >= 0.
+ * This value is relative to the {@link #getChildAt(int) index} values in the normal
+ * child list of this container, where any transient view at a particular index will
+ * be drawn before any normal child at that same index.
+ */
+ public void addTransientView(View view, int index) {
+ if (index < 0) {
+ return;
+ }
+ if (mTransientIndices == null) {
+ mTransientIndices = new ArrayList<Integer>();
+ mTransientViews = new ArrayList<View>();
+ }
+ final int oldSize = mTransientIndices.size();
+ if (oldSize > 0) {
+ int insertionIndex;
+ for (insertionIndex = 0; insertionIndex < oldSize; ++insertionIndex) {
+ if (index < mTransientIndices.get(insertionIndex)) {
+ break;
+ }
+ }
+ mTransientIndices.add(insertionIndex, index);
+ mTransientViews.add(insertionIndex, view);
+ } else {
+ mTransientIndices.add(index);
+ mTransientViews.add(view);
+ }
+ view.mParent = this;
+ view.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
+ invalidate(true);
+ }
+
+ /**
+ * Removes a view from the list of transient views in this container. If there is no
+ * such transient view, this method does nothing.
+ *
+ * @param view The transient view to be removed
+ */
+ public void removeTransientView(View view) {
+ if (mTransientViews == null) {
+ return;
+ }
+ final int size = mTransientViews.size();
+ for (int i = 0; i < size; ++i) {
+ if (view == mTransientViews.get(i)) {
+ mTransientViews.remove(i);
+ mTransientIndices.remove(i);
+ view.mParent = null;
+ view.dispatchDetachedFromWindow();
+ invalidate(true);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Returns the number of transient views in this container. Specific transient
+ * views and the index at which they were added can be retrieved via
+ * {@link #getTransientView(int)} and {@link #getTransientViewIndex(int)}.
+ *
+ * @see #addTransientView(View, int)
+ * @return The number of transient views in this container
+ */
+ public int getTransientViewCount() {
+ return mTransientIndices == null ? 0 : mTransientIndices.size();
+ }
+
+ /**
+ * Given a valid position within the list of transient views, returns the index of
+ * the transient view at that position.
+ *
+ * @param position The position of the index being queried. Must be at least 0
+ * and less than the value returned by {@link #getTransientViewCount()}.
+ * @return The index of the transient view stored in the given position if the
+ * position is valid, otherwise -1
+ */
+ public int getTransientViewIndex(int position) {
+ if (position < 0 || mTransientIndices == null || position >= mTransientIndices.size()) {
+ return -1;
+ }
+ return mTransientIndices.get(position);
+ }
+
+ /**
+ * Given a valid position within the list of transient views, returns the
+ * transient view at that position.
+ *
+ * @param position The position of the view being queried. Must be at least 0
+ * and less than the value returned by {@link #getTransientViewCount()}.
+ * @return The transient view stored in the given position if the
+ * position is valid, otherwise null
+ */
+ public View getTransientView(int position) {
+ if (mTransientViews == null || position >= mTransientViews.size()) {
+ return null;
+ }
+ return mTransientViews.get(position);
+ }
+
+ /**
* <p>Adds a child view. If no layout parameters are already set on the child, the
* default parameters for this ViewGroup are set on the child.</p>
*
@@ -4096,6 +4265,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (child.getVisibility() != View.GONE) {
notifySubtreeAccessibilityStateChangedIfNeeded();
}
+
+ if (mTransientIndices != null) {
+ final int transientCount = mTransientIndices.size();
+ for (int i = 0; i < transientCount; ++i) {
+ final int oldIndex = mTransientIndices.get(i);
+ if (index <= oldIndex) {
+ mTransientIndices.set(i, oldIndex + 1);
+ }
+ }
+ }
}
private void addInArray(View child, int index) {
@@ -4340,6 +4519,14 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (view.getVisibility() != View.GONE) {
notifySubtreeAccessibilityStateChangedIfNeeded();
}
+
+ int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
+ for (int i = 0; i < transientCount; ++i) {
+ final int oldIndex = mTransientIndices.get(i);
+ if (index < oldIndex) {
+ mTransientIndices.set(i, oldIndex - 1);
+ }
+ }
}
/**