diff options
author | Chet Haase <chet@google.com> | 2013-03-26 07:55:30 -0700 |
---|---|---|
committer | Chet Haase <chet@google.com> | 2013-04-08 07:30:12 -0700 |
commit | edf6f4b49f6e77c349f5055372ce381b74f12efb (patch) | |
tree | a506b5eecd2c19017f46dc9f5982e0a8de3078ef /core/java/android/view | |
parent | a56b78dcd1292a4291d85113bdeeda8496c1a0c0 (diff) | |
download | frameworks_base-edf6f4b49f6e77c349f5055372ce381b74f12efb.zip frameworks_base-edf6f4b49f6e77c349f5055372ce381b74f12efb.tar.gz frameworks_base-edf6f4b49f6e77c349f5055372ce381b74f12efb.tar.bz2 |
Make adding views specific to a ViewGroup's overlay
Adding views to views (possible with the new Overlay API) is weird.
This change moves the view-management facilities of Overlay to a subclass
that is specific to the overlay returned from ViewGroup.getOverlay().
So now you can add drawables to all view overlays, but only add/remove
views to/from the overlay returned from ViewGroup.getOverlay().
Also, the previous approach of using an interface for Overlay was
changed to classes for both ViewOverlay and ViewGroupOverlay.
Finally, this change makes not handling touch correctly the proper,
and documented, behavior of overlay views. There are various tricky issues
to sort out with input in overlays (including click handling as well as focus)
and we don't want developers starting to use overlays as some kind of general
container hierarchy, so we're purposely constraining overlays to have visual-only
behavior.
Issue #8459085 Overlay needs to handle touch correctly
Change-Id: I207b8dbf528f87c92369d270d8b0a6556826d207
Diffstat (limited to 'core/java/android/view')
-rw-r--r-- | core/java/android/view/View.java | 44 | ||||
-rw-r--r-- | core/java/android/view/ViewGroup.java | 57 | ||||
-rw-r--r-- | core/java/android/view/ViewGroupOverlay.java (renamed from core/java/android/view/Overlay.java) | 60 | ||||
-rw-r--r-- | core/java/android/view/ViewOverlay.java | 393 |
4 files changed, 303 insertions, 251 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 3b06da7..a520e17 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -12107,7 +12107,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, //System.out.println("Attached! " + this); mAttachInfo = info; if (mOverlay != null) { - mOverlay.dispatchAttachedToWindow(info, visibility); + mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility); } mWindowAttachCount++; // We will need to evaluate the drawable state at least once. @@ -12178,7 +12178,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mAttachInfo = null; if (mOverlay != null) { - mOverlay.dispatchDetachedFromWindow(); + mOverlay.getOverlayView().dispatchDetachedFromWindow(); } } @@ -12831,7 +12831,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { dispatchDraw(canvas); if (mOverlay != null && !mOverlay.isEmpty()) { - mOverlay.draw(canvas); + mOverlay.getOverlayView().draw(canvas); } } else { draw(canvas); @@ -13147,7 +13147,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags &= ~PFLAG_DIRTY_MASK; dispatchDraw(canvas); if (mOverlay != null && !mOverlay.isEmpty()) { - mOverlay.draw(canvas); + mOverlay.getOverlayView().draw(canvas); } } else { draw(canvas); @@ -13905,7 +13905,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, onDrawScrollBars(canvas); if (mOverlay != null && !mOverlay.isEmpty()) { - mOverlay.dispatchDraw(canvas); + mOverlay.getOverlayView().dispatchDraw(canvas); } // we're done... @@ -14049,34 +14049,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback, onDrawScrollBars(canvas); if (mOverlay != null && !mOverlay.isEmpty()) { - mOverlay.dispatchDraw(canvas); + mOverlay.getOverlayView().dispatchDraw(canvas); } } /** - * Called by the addToOverlay() methods to create, attach, and size the overlay as necessary + * Returns the overlay for this view, creating it if it does not yet exist. + * Adding drawables to the overlay will cause them to be displayed whenever + * the view itself is redrawn. Objects in the overlay should be actively + * managed: remove them when they should not be displayed anymore. The + * overlay will always have the same size as its host view. + * + * @return The ViewOverlay object for this view. + * @see ViewOverlay */ - private void setupOverlay() { + public ViewOverlay getOverlay() { if (mOverlay == null) { mOverlay = new ViewOverlay(mContext, this); - mOverlay.mAttachInfo = mAttachInfo; - mOverlay.setRight(mRight); - mOverlay.setBottom(mBottom); } - } - - /** - * Returns the overlay for this view, creating it if it does not yet exist. Adding drawables - * and/or views to the overlay will cause them to be displayed whenever the view itself is - * redrawn. Objects in the overlay should be actively managed: remove them when they should - * not be displayed anymore and invalidate this view appropriately when overlay drawables - * change. The overlay will always have the same size as its host view. - * - * @return The Overlay object for this view. - * @see Overlay - */ - public Overlay getOverlay() { - setupOverlay(); return mOverlay; } @@ -14360,8 +14350,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) { onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); if (mOverlay != null) { - mOverlay.setRight(mRight); - mOverlay.setBottom(mBottom); + mOverlay.getOverlayView().setRight(newWidth); + mOverlay.getOverlayView().setBottom(newHeight); } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index f615e1bc..c07191a 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -1876,34 +1876,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // have become out of sync. removePointersFromTouchTargets(idBitsToAssign); - final float x = ev.getX(actionIndex); - final float y = ev.getY(actionIndex); - - if (mOverlay != null) { - ViewOverlay overlay = (ViewOverlay) mOverlay; - // Check to see whether the overlay can handle the event - final View child = mOverlay; - if (canViewReceivePointerEvents(child) && - isTransformedTouchPointInView(x, y, child, null)) { - newTouchTarget = getTouchTarget(child); - if (newTouchTarget != null) { - newTouchTarget.pointerIdBits |= idBitsToAssign; - } else { - resetCancelNextUpFlag(child); - if (dispatchTransformedTouchEvent(ev, false, child, - idBitsToAssign)) { - mLastTouchDownTime = ev.getDownTime(); - mLastTouchDownX = ev.getX(); - mLastTouchDownY = ev.getY(); - newTouchTarget = addTouchTarget(child, idBitsToAssign); - alreadyDispatchedToNewTouchTarget = true; - } - } - } - } - final int childrenCount = mChildrenCount; if (newTouchTarget == null && childrenCount != 0) { + final float x = ev.getX(actionIndex); + final float y = ev.getY(actionIndex); // Find a child that can receive the event. // Scan children from front to back. final View[] children = mChildren; @@ -2991,6 +2967,26 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** + * Returns the ViewGroupOverlay for this view group, creating it if it does + * not yet exist. In addition to {@link ViewOverlay}'s support for drawables, + * {@link ViewGroupOverlay} allows views to be added to the overlay. These + * views, like overlay drawables, are visual-only; they do not receive input + * events and should not be used as anything other than a temporary + * representation of a view in a parent container, such as might be used + * by an animation effect. + * + * @return The ViewGroupOverlay object for this view. + * @see ViewGroupOverlay + */ + @Override + public ViewGroupOverlay getOverlay() { + if (mOverlay == null) { + mOverlay = new ViewGroupOverlay(mContext, this); + } + return (ViewGroupOverlay) mOverlay; + } + + /** * Returns the index of the child to draw for this iteration. Override this * if you want to change the drawing order of children. By default, it * returns i. @@ -3055,11 +3051,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } if (mOverlay != null) { - mOverlay.mRecreateDisplayList = (mOverlay.mPrivateFlags & PFLAG_INVALIDATED) + View overlayView = mOverlay.getOverlayView(); + overlayView.mRecreateDisplayList = (overlayView.mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED; - mOverlay.mPrivateFlags &= ~PFLAG_INVALIDATED; - mOverlay.getDisplayList(); - mOverlay.mRecreateDisplayList = false; + overlayView.mPrivateFlags &= ~PFLAG_INVALIDATED; + overlayView.getDisplayList(); + overlayView.mRecreateDisplayList = false; } } diff --git a/core/java/android/view/Overlay.java b/core/java/android/view/ViewGroupOverlay.java index 6630752..c1b24f2 100644 --- a/core/java/android/view/Overlay.java +++ b/core/java/android/view/ViewGroupOverlay.java @@ -15,43 +15,37 @@ */ package android.view; +import android.content.Context; import android.graphics.drawable.Drawable; /** - * An overlay is an extra layer that sits on top of a View (the "host view") - * which is drawn after all other content in that view (including children, - * if the view is a ViewGroup). Interaction with the overlay layer is done in - * terms of adding/removing views and drawables. + * A group overlay is an extra layer that sits on top of a ViewGroup + * (the "host view") which is drawn after all other content in that view + * (including the view group's children). Interaction with the overlay + * layer is done by adding and removing views and drawables. * - * @see android.view.View#getOverlay() + * <p>ViewGroupOverlay is a subclass of {@link ViewOverlay}, adding the ability to + * manage views for overlays on ViewGroups, in addition to the drawable + * support in ViewOverlay.</p> + * + * @see ViewGroup#getOverlay() */ -public interface Overlay { +public class ViewGroupOverlay extends ViewOverlay { - /** - * Adds a Drawable to the overlay. The bounds of the drawable should be relative to - * the host view. Any drawable added to the overlay should be removed when it is no longer - * needed or no longer visible. - * - * @param drawable The Drawable to be added to the overlay. This drawable will be - * drawn when the view redraws its overlay. - * @see #remove(android.graphics.drawable.Drawable) - * @see #add(View) - */ - void add(Drawable drawable); - - /** - * Removes the specified Drawable from the overlay. - * - * @param drawable The Drawable to be removed from the overlay. - * @see #add(android.graphics.drawable.Drawable) - */ - void remove(Drawable drawable); + ViewGroupOverlay(Context context, View hostView) { + super(context, hostView); + } /** * Adds a View to the overlay. The bounds of the added view should be * relative to the host view. Any view added to the overlay should be * removed when it is no longer needed or no longer visible. * + * <p>Views in the overlay are visual-only; they do not receive input + * events and do not participate in focus traversal. Overlay views + * are intended to be transient, such as might be needed by a temporary + * animation effect.</p> + * * <p>If the view has a parent, the view will be removed from that parent * before being added to the overlay. Also, the view will be repositioned * such that it is in the same relative location inside the activity. For @@ -62,20 +56,20 @@ public interface Overlay { * @param view The View to be added to the overlay. The added view will be * drawn when the overlay is drawn. * @see #remove(View) - * @see #add(android.graphics.drawable.Drawable) + * @see ViewOverlay#add(Drawable) */ - void add(View view); + public void add(View view) { + mOverlayViewGroup.add(view); + } /** * Removes the specified View from the overlay. * * @param view The View to be removed from the overlay. * @see #add(View) + * @see ViewOverlay#remove(Drawable) */ - void remove(View view); - - /** - * Removes all views and drawables from the overlay. - */ - void clear(); + public void remove(View view) { + mOverlayViewGroup.remove(view); + } } diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java index 8b18d53..78e2597 100644 --- a/core/java/android/view/ViewOverlay.java +++ b/core/java/android/view/ViewOverlay.java @@ -23,215 +23,286 @@ import android.graphics.drawable.Drawable; import java.util.ArrayList; /** - * ViewOverlay is a container that View uses to host all objects (views and - * drawables) that are added to its "overlay", gotten through - * {@link View#getOverlay()}. Views and drawables are added to the overlay - * via the add/remove methods in this class. These views and drawables are - * drawn whenever the view itself is drawn; first the view draws its own - * content (and children, if it is a ViewGroup), then it draws its overlay - * (if it has one). + * An overlay is an extra layer that sits on top of a View (the "host view") + * which is drawn after all other content in that view (including children, + * if the view is a ViewGroup). Interaction with the overlay layer is done + * by adding and removing drawables. * - * Besides managing and drawing the list of drawables, this class serves - * two purposes: - * (1) it noops layout calls because children are absolutely positioned and - * (2) it forwards all invalidation calls to its host view. The invalidation - * redirect is necessary because the overlay is not a child of the host view - * and invalidation cannot therefore follow the normal path up through the - * parent hierarchy. + * <p>An overlay requested from a ViewGroup is of type {@link ViewGroupOverlay}, + * which also supports adding and removing views.</p> * - * @hide + * @see View#getOverlay() View.getOverlay() + * @see ViewGroup#getOverlay() ViewGroup.getOverlay() + * @see ViewGroupOverlay */ -class ViewOverlay extends ViewGroup implements Overlay { +public class ViewOverlay { /** - * The View for which this is an overlay. Invalidations of the overlay are redirected to - * this host view. + * The actual container for the drawables (and views, if it's a ViewGroupOverlay). + * All of the management and rendering details for the overlay are handled in + * OverlayViewGroup. */ - View mHostView; + OverlayViewGroup mOverlayViewGroup; + + ViewOverlay(Context context, View hostView) { + mOverlayViewGroup = new OverlayViewGroup(context, hostView); + } /** - * The set of drawables to draw when the overlay is rendered. + * Used internally by View and ViewGroup to handle drawing and invalidation + * of the overlay + * @return */ - ArrayList<Drawable> mDrawables = null; - - ViewOverlay(Context context, View host) { - super(context); - mHostView = host; - mParent = mHostView.getParent(); + ViewGroup getOverlayView() { + return mOverlayViewGroup; } - @Override + /** + * Adds a Drawable to the overlay. The bounds of the drawable should be relative to + * the host view. Any drawable added to the overlay should be removed when it is no longer + * needed or no longer visible. + * + * @param drawable The Drawable to be added to the overlay. This drawable will be + * drawn when the view redraws its overlay. + * @see #remove(Drawable) + */ public void add(Drawable drawable) { - if (mDrawables == null) { - mDrawables = new ArrayList<Drawable>(); - } - if (!mDrawables.contains(drawable)) { - // Make each drawable unique in the overlay; can't add it more than once - mDrawables.add(drawable); - invalidate(drawable.getBounds()); - drawable.setCallback(this); - } + mOverlayViewGroup.add(drawable); } - @Override + /** + * Removes the specified Drawable from the overlay. + * + * @param drawable The Drawable to be removed from the overlay. + * @see #add(Drawable) + */ public void remove(Drawable drawable) { - if (mDrawables != null) { - mDrawables.remove(drawable); - invalidate(drawable.getBounds()); - drawable.setCallback(null); - } + mOverlayViewGroup.remove(drawable); } - @Override - public void invalidateDrawable(Drawable drawable) { - invalidate(drawable.getBounds()); + /** + * Removes all content from the overlay. + */ + public void clear() { + mOverlayViewGroup.clear(); } - @Override - public void add(View child) { - int deltaX = 0; - int deltaY = 0; - if (child.getParent() instanceof ViewGroup) { - ViewGroup parent = (ViewGroup) child.getParent(); - if (parent != mHostView) { - // Moving to different container; figure out how to position child such that - // it is in the same location on the screen - int[] parentLocation = new int[2]; - int[] hostViewLocation = new int[2]; - parent.getLocationOnScreen(parentLocation); - mHostView.getLocationOnScreen(hostViewLocation); - child.offsetLeftAndRight(parentLocation[0] - hostViewLocation[0]); - child.offsetTopAndBottom(parentLocation[1] - hostViewLocation[1]); + boolean isEmpty() { + return mOverlayViewGroup.isEmpty(); + } + + /** + * OverlayViewGroup is a container that View and ViewGroup use to host + * drawables and views added to their overlays ({@link ViewOverlay} and + * {@link ViewGroupOverlay}, respectively). Drawables are added to the overlay + * via the add/remove methods in ViewOverlay, Views are added/removed via + * ViewGroupOverlay. These drawable and view objects are + * drawn whenever the view itself is drawn; first the view draws its own + * content (and children, if it is a ViewGroup), then it draws its overlay + * (if it has one). + * + * <p>Besides managing and drawing the list of drawables, this class serves + * two purposes: + * (1) it noops layout calls because children are absolutely positioned and + * (2) it forwards all invalidation calls to its host view. The invalidation + * redirect is necessary because the overlay is not a child of the host view + * and invalidation cannot therefore follow the normal path up through the + * parent hierarchy.</p> + * + * @see View#getOverlay() + * @see ViewGroup#getOverlay() + */ + static class OverlayViewGroup extends ViewGroup { + + /** + * The View for which this is an overlay. Invalidations of the overlay are redirected to + * this host view. + */ + View mHostView; + + /** + * The set of drawables to draw when the overlay is rendered. + */ + ArrayList<Drawable> mDrawables = null; + + OverlayViewGroup(Context context, View hostView) { + super(context); + mHostView = hostView; + mAttachInfo = mHostView.mAttachInfo; + mRight = hostView.getWidth(); + mBottom = hostView.getHeight(); + } + + public void add(Drawable drawable) { + if (mDrawables == null) { + + mDrawables = new ArrayList<Drawable>(); + } + if (!mDrawables.contains(drawable)) { + // Make each drawable unique in the overlay; can't add it more than once + mDrawables.add(drawable); + invalidate(drawable.getBounds()); + drawable.setCallback(this); } - parent.removeView(child); } - super.addView(child); - } - @Override - public void remove(View view) { - super.removeView(view); - } + public void remove(Drawable drawable) { + if (mDrawables != null) { + mDrawables.remove(drawable); + invalidate(drawable.getBounds()); + drawable.setCallback(null); + } + } - @Override - public void clear() { - removeAllViews(); - mDrawables.clear(); - } + public void add(View child) { + if (child.getParent() instanceof ViewGroup) { + ViewGroup parent = (ViewGroup) child.getParent(); + if (parent != mHostView) { + // Moving to different container; figure out how to position child such that + // it is in the same location on the screen + int[] parentLocation = new int[2]; + int[] hostViewLocation = new int[2]; + parent.getLocationOnScreen(parentLocation); + mHostView.getLocationOnScreen(hostViewLocation); + child.offsetLeftAndRight(parentLocation[0] - hostViewLocation[0]); + child.offsetTopAndBottom(parentLocation[1] - hostViewLocation[1]); + } + parent.removeView(child); + } + super.addView(child); + } - boolean isEmpty() { - if (getChildCount() == 0 && (mDrawables == null || mDrawables.size() == 0)) { - return true; + public void remove(View view) { + super.removeView(view); } - return false; - } - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size(); - for (int i = 0; i < numDrawables; ++i) { - mDrawables.get(i).draw(canvas); + public void clear() { + removeAllViews(); + mDrawables.clear(); } - } - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - // Noop: children are positioned absolutely - } + boolean isEmpty() { + if (getChildCount() == 0 && + (mDrawables == null || mDrawables.size() == 0)) { + return true; + } + return false; + } - /* - The following invalidation overrides exist for the purpose of redirecting invalidation to - the host view. The overlay is not parented to the host view (since a View cannot be a parent), - so the invalidation cannot proceed through the normal parent hierarchy. - There is a built-in assumption that the overlay exactly covers the host view, therefore - the invalidation rectangles received do not need to be adjusted when forwarded to - the host view. - */ + @Override + public void invalidateDrawable(Drawable drawable) { + invalidate(drawable.getBounds()); + } - @Override - public void invalidate(Rect dirty) { - super.invalidate(dirty); - if (mHostView != null) { - mHostView.invalidate(dirty); + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size(); + for (int i = 0; i < numDrawables; ++i) { + mDrawables.get(i).draw(canvas); + } } - } - @Override - public void invalidate(int l, int t, int r, int b) { - super.invalidate(l, t, r, b); - if (mHostView != null) { - mHostView.invalidate(l, t, r, b); + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + // Noop: children are positioned absolutely } - } - @Override - public void invalidate() { - super.invalidate(); - if (mHostView != null) { - mHostView.invalidate(); + /* + The following invalidation overrides exist for the purpose of redirecting invalidation to + the host view. The overlay is not parented to the host view (since a View cannot be a + parent), so the invalidation cannot proceed through the normal parent hierarchy. + There is a built-in assumption that the overlay exactly covers the host view, therefore + the invalidation rectangles received do not need to be adjusted when forwarded to + the host view. + */ + + @Override + public void invalidate(Rect dirty) { + super.invalidate(dirty); + if (mHostView != null) { + mHostView.invalidate(dirty); + } } - } - @Override - void invalidate(boolean invalidateCache) { - super.invalidate(invalidateCache); - if (mHostView != null) { - mHostView.invalidate(invalidateCache); + @Override + public void invalidate(int l, int t, int r, int b) { + super.invalidate(l, t, r, b); + if (mHostView != null) { + mHostView.invalidate(l, t, r, b); + } } - } - @Override - void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { - super.invalidateViewProperty(invalidateParent, forceRedraw); - if (mHostView != null) { - mHostView.invalidateViewProperty(invalidateParent, forceRedraw); + @Override + public void invalidate() { + super.invalidate(); + if (mHostView != null) { + mHostView.invalidate(); + } } - } - @Override - protected void invalidateParentCaches() { - super.invalidateParentCaches(); - if (mHostView != null) { - mHostView.invalidateParentCaches(); + @Override + void invalidate(boolean invalidateCache) { + super.invalidate(invalidateCache); + if (mHostView != null) { + mHostView.invalidate(invalidateCache); + } } - } - @Override - protected void invalidateParentIfNeeded() { - super.invalidateParentIfNeeded(); - if (mHostView != null) { - mHostView.invalidateParentIfNeeded(); + @Override + void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { + super.invalidateViewProperty(invalidateParent, forceRedraw); + if (mHostView != null) { + mHostView.invalidateViewProperty(invalidateParent, forceRedraw); + } } - } - public void invalidateChildFast(View child, final Rect dirty) { - if (mHostView != null) { - // Note: This is not a "fast" invalidation. Would be nice to instead invalidate using DL - // properties and a dirty rect instead of causing a real invalidation of the host view - int left = child.mLeft; - int top = child.mTop; - if (!child.getMatrix().isIdentity()) { - child.transformRect(dirty); + @Override + protected void invalidateParentCaches() { + super.invalidateParentCaches(); + if (mHostView != null) { + mHostView.invalidateParentCaches(); + } + } + + @Override + protected void invalidateParentIfNeeded() { + super.invalidateParentIfNeeded(); + if (mHostView != null) { + mHostView.invalidateParentIfNeeded(); } - dirty.offset(left, top); - mHostView.invalidate(dirty); } - } - @Override - public ViewParent invalidateChildInParent(int[] location, Rect dirty) { - if (mHostView != null) { - dirty.offset(location[0], location[1]); - if (mHostView instanceof ViewGroup) { - location[0] = 0; - location[1] = 0; - super.invalidateChildInParent(location, dirty); - return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty); - } else { - invalidate(dirty); + public void invalidateChildFast(View child, final Rect dirty) { + if (mHostView != null) { + // Note: This is not a "fast" invalidation. Would be nice to instead invalidate + // using DisplayList properties and a dirty rect instead of causing a real + // invalidation of the host view + int left = child.mLeft; + int top = child.mTop; + if (!child.getMatrix().isIdentity()) { + child.transformRect(dirty); + } + dirty.offset(left, top); + mHostView.invalidate(dirty); } } - return null; + + @Override + public ViewParent invalidateChildInParent(int[] location, Rect dirty) { + if (mHostView != null) { + dirty.offset(location[0], location[1]); + if (mHostView instanceof ViewGroup) { + location[0] = 0; + location[1] = 0; + super.invalidateChildInParent(location, dirty); + return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty); + } else { + invalidate(dirty); + } + } + return null; + } } + } |