diff options
| -rw-r--r-- | api/current.txt | 5 | ||||
| -rw-r--r-- | api/system-current.txt | 5 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 187 |
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); + } + } } /** |