Merge "Handle animations in Views' rectangle clipping methods." into ics-mr1

This commit is contained in:
Gilles Debunne
2011-12-02 15:28:56 -08:00
committed by Android (Google) Code Review
3 changed files with 98 additions and 38 deletions

View File

@@ -8059,9 +8059,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/** /**
* If some part of this view is not clipped by any of its parents, then * If some part of this view is not clipped by any of its parents, then
* return that area in r in global (root) coordinates. To convert r to local * return that area in r in global (root) coordinates. To convert r to local
* coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x, * coordinates (without taking possible View rotations into account), offset
* -globalOffset.y)) If the view is completely clipped or translated out, * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
* return false. * If the view is completely clipped or translated out, return false.
* *
* @param r If true is returned, r holds the global coordinates of the * @param r If true is returned, r holds the global coordinates of the
* visible portion of this view. * visible portion of this view.
@@ -12152,35 +12152,48 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* @param location an array of two integers in which to hold the coordinates * @param location an array of two integers in which to hold the coordinates
*/ */
public void getLocationInWindow(int[] location) { public void getLocationInWindow(int[] location) {
// When the view is not attached to a window, this method does not make sense
if (mAttachInfo == null) return;
if (location == null || location.length < 2) { if (location == null || location.length < 2) {
throw new IllegalArgumentException("location must be an array of " throw new IllegalArgumentException("location must be an array of two integers");
+ "two integers");
} }
location[0] = mLeft; float[] position = mAttachInfo.mTmpTransformLocation;
location[1] = mTop; position[0] = position[1] = 0.0f;
if (mTransformationInfo != null) {
location[0] += (int) (mTransformationInfo.mTranslationX + 0.5f); if (!hasIdentityMatrix()) {
location[1] += (int) (mTransformationInfo.mTranslationY + 0.5f); getMatrix().mapPoints(position);
} }
position[0] += mLeft;
position[1] += mTop;
ViewParent viewParent = mParent; ViewParent viewParent = mParent;
while (viewParent instanceof View) { while (viewParent instanceof View) {
final View view = (View)viewParent; final View view = (View) viewParent;
location[0] += view.mLeft - view.mScrollX;
location[1] += view.mTop - view.mScrollY; position[0] -= view.mScrollX;
if (view.mTransformationInfo != null) { position[1] -= view.mScrollY;
location[0] += (int) (view.mTransformationInfo.mTranslationX + 0.5f);
location[1] += (int) (view.mTransformationInfo.mTranslationY + 0.5f); if (!view.hasIdentityMatrix()) {
view.getMatrix().mapPoints(position);
} }
position[0] += view.mLeft;
position[1] += view.mTop;
viewParent = view.mParent; viewParent = view.mParent;
} }
if (viewParent instanceof ViewRootImpl) { if (viewParent instanceof ViewRootImpl) {
// *cough* // *cough*
final ViewRootImpl vr = (ViewRootImpl)viewParent; final ViewRootImpl vr = (ViewRootImpl) viewParent;
location[1] -= vr.mCurScrollY; position[1] -= vr.mCurScrollY;
} }
location[0] = (int) (position[0] + 0.5f);
location[1] = (int) (position[1] + 0.5f);
} }
/** /**

View File

@@ -79,7 +79,7 @@ import java.util.HashSet;
public abstract class ViewGroup extends View implements ViewParent, ViewManager { public abstract class ViewGroup extends View implements ViewParent, ViewManager {
private static final boolean DBG = false; private static final boolean DBG = false;
/** /**
* Views which have been hidden or removed which need to be animated on * Views which have been hidden or removed which need to be animated on
* their way out. * their way out.
@@ -4182,15 +4182,42 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* {@inheritDoc} * {@inheritDoc}
*/ */
public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) { public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
// The View is not attached to a window, 'visible' does not make sense, return false
if (mAttachInfo == null) return false;
final RectF rect = mAttachInfo.mTmpTransformRect;
rect.set(r);
if (!child.hasIdentityMatrix()) {
child.getMatrix().mapRect(rect);
}
int dx = child.mLeft - mScrollX; int dx = child.mLeft - mScrollX;
int dy = child.mTop - mScrollY; int dy = child.mTop - mScrollY;
rect.offset(dx, dy);
if (offset != null) { if (offset != null) {
if (!child.hasIdentityMatrix()) {
float[] position = mAttachInfo.mTmpTransformLocation;
position[0] = offset.x;
position[1] = offset.y;
child.getMatrix().mapPoints(position);
offset.x = (int) (position[0] + 0.5f);
offset.y = (int) (position[1] + 0.5f);
}
offset.x += dx; offset.x += dx;
offset.y += dy; offset.y += dy;
} }
r.offset(dx, dy);
return r.intersect(0, 0, mRight - mLeft, mBottom - mTop) && if (rect.intersect(0, 0, mRight - mLeft, mBottom - mTop)) {
(mParent == null || mParent.getChildVisibleRect(this, r, offset)); if (mParent == null) return true;
r.set((int) (rect.left + 0.5f), (int) (rect.top + 0.5f),
(int) (rect.right + 0.5f), (int) (rect.bottom + 0.5f));
return mParent.getChildVisibleRect(this, r, offset);
}
return false;
} }
/** /**

View File

@@ -63,16 +63,16 @@ public interface ViewParent {
/** /**
* All or part of a child is dirty and needs to be redrawn. * All or part of a child is dirty and needs to be redrawn.
* *
* The location array is an array of two int values which respectively * <p>The location array is an array of two int values which respectively
* define the left and the top position of the dirty child. * define the left and the top position of the dirty child.</p>
* *
* This method must return the parent of this ViewParent if the specified * <p>This method must return the parent of this ViewParent if the specified
* rectangle must be invalidated in the parent. If the specified rectangle * rectangle must be invalidated in the parent. If the specified rectangle
* does not require invalidation in the parent or if the parent does not * does not require invalidation in the parent or if the parent does not
* exist, this method must return null. * exist, this method must return null.</p>
* *
* When this method returns a non-null value, the location array must * <p>When this method returns a non-null value, the location array must
* have been updated with the left and top coordinates of this ViewParent. * have been updated with the left and top coordinates of this ViewParent.</p>
* *
* @param location An array of 2 ints containing the left and top * @param location An array of 2 ints containing the left and top
* coordinates of the child to invalidate * coordinates of the child to invalidate
@@ -115,6 +115,26 @@ public interface ViewParent {
*/ */
public void clearChildFocus(View child); public void clearChildFocus(View child);
/**
* Compute the visible part of a rectangular region defined in terms of a child view's
* coordinates.
*
* <p>Returns the clipped visible part of the rectangle <code>r</code>, defined in the
* <code>child</code>'s local coordinate system. <code>r</code> is modified by this method to
* contain the result, expressed in the global (root) coordinate system.</p>
*
* <p>The resulting rectangle is always axis aligned. If a rotation is applied to a node in the
* View hierarchy, the result is the axis-aligned bounding box of the visible rectangle.</p>
*
* @param child A child View, whose rectangular visible region we want to compute
* @param r The input rectangle, defined in the child coordinate system. Will be overwritten to
* contain the resulting visible rectangle, expressed in global (root) coordinates
* @param offset The input coordinates of a point, defined in the child coordinate system.
* As with the <code>r</code> parameter, this will be overwritten to contain the global (root)
* coordinates of that point.
* A <code>null</code> value is valid (in case you are not interested in this result)
* @return true if the resulting rectangle is not empty, false otherwise
*/
public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset); public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset);
/** /**
@@ -143,11 +163,11 @@ public interface ViewParent {
/** /**
* Bring up a context menu for the specified view or its ancestors. * Bring up a context menu for the specified view or its ancestors.
* <p> *
* In most cases, a subclass does not need to override this. However, if * <p>In most cases, a subclass does not need to override this. However, if
* the subclass is added directly to the window manager (for example, * the subclass is added directly to the window manager (for example,
* {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)}) * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
* then it should override this and show the context menu. * then it should override this and show the context menu.</p>
* *
* @param originalView The source view where the context menu was first invoked * @param originalView The source view where the context menu was first invoked
* @return true if a context menu was displayed * @return true if a context menu was displayed
@@ -164,11 +184,11 @@ public interface ViewParent {
/** /**
* Start an action mode for the specified view. * Start an action mode for the specified view.
* <p> *
* In most cases, a subclass does not need to override this. However, if the * <p>In most cases, a subclass does not need to override this. However, if the
* subclass is added directly to the window manager (for example, * subclass is added directly to the window manager (for example,
* {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)}) * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
* then it should override this and start the action mode. * then it should override this and start the action mode.</p>
* *
* @param originalView The source view where the action mode was first invoked * @param originalView The source view where the action mode was first invoked
* @param callback The callback that will handle lifecycle events for the action mode * @param callback The callback that will handle lifecycle events for the action mode
@@ -188,10 +208,10 @@ public interface ViewParent {
* Called when a child does not want this parent and its ancestors to * Called when a child does not want this parent and its ancestors to
* intercept touch events with * intercept touch events with
* {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}. * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
* <p> *
* This parent should pass this call onto its parents. This parent must obey * <p>This parent should pass this call onto its parents. This parent must obey
* this request for the duration of the touch (that is, only clear the flag * this request for the duration of the touch (that is, only clear the flag
* after this parent has received an up or a cancel. * after this parent has received an up or a cancel.</p>
* *
* @param disallowIntercept True if the child does not want the parent to * @param disallowIntercept True if the child does not want the parent to
* intercept touch events. * intercept touch events.
@@ -234,7 +254,7 @@ public interface ViewParent {
* the sending. The parent can optionally add a record for itself before * the sending. The parent can optionally add a record for itself before
* dispatching the request to its parent. A parent can also choose not to * dispatching the request to its parent. A parent can also choose not to
* respect the request for sending the event. The accessibility event is sent * respect the request for sending the event. The accessibility event is sent
* by the topmost view in the view tree. * by the topmost view in the view tree.</p>
* *
* @param child The child which requests sending the event. * @param child The child which requests sending the event.
* @param event The event to be sent. * @param event The event to be sent.