am bc6c050f: Merge "Fix touch processing for Overlay views" into jb-mr2-dev

* commit 'bc6c050f9c603159c526cc7d60ec9159c57359e7':
  Fix touch processing for Overlay views
This commit is contained in:
Chet Haase
2013-03-26 01:57:59 +00:00
committed by Android Git Automerger
4 changed files with 82 additions and 45 deletions

View File

@@ -18,9 +18,10 @@ package android.view;
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.
* 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.
*
* @see android.view.View#getOverlay()
*/
@@ -47,10 +48,16 @@ public interface Overlay {
void remove(Drawable drawable);
/**
* 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. The view must not be parented elsewhere when it is added
* to the overlay.
* 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>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
* example, if the view's current parent lies 100 pixels to the right
* and 200 pixels down from the origin of the overlay's
* host view, then the view will be offset by (100, 200).</p>
*
* @param view The View to be added to the overlay. The added view will be
* drawn when the overlay is drawn.

View File

@@ -12098,7 +12098,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
//System.out.println("Attached! " + this);
mAttachInfo = info;
if (mOverlay != null) {
mOverlay.mAttachInfo = info;
mOverlay.dispatchAttachedToWindow(info, visibility);
}
mWindowAttachCount++;
// We will need to evaluate the drawable state at least once.
@@ -12169,7 +12169,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mAttachInfo = null;
if (mOverlay != null) {
mOverlay.mAttachInfo = null;
mOverlay.dispatchDetachedFromWindow();
}
}

View File

@@ -1868,13 +1868,37 @@ 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 (childrenCount != 0 || mOverlay != null) {
if (newTouchTarget == null && childrenCount != 0) {
// Find a child that can receive the event.
// Scan children from front to back.
final View[] children = mChildren;
final float x = ev.getX(actionIndex);
final float y = ev.getY(actionIndex);
final boolean customOrder = isChildrenDrawingOrderEnabled();
for (int i = childrenCount - 1; i >= 0; i--) {
@@ -1906,27 +1930,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
break;
}
}
if (mOverlay != null && newTouchTarget == null) {
// 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;
}
}
}
}
}
if (newTouchTarget == null && mFirstTouchTarget != null) {
@@ -1957,7 +1960,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
handled = true;
} else {
final boolean cancelChild = resetCancelNextUpFlag(target.child)
|| intercepted;
|| intercepted;
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;

View File

@@ -23,17 +23,21 @@ 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).
* 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).
*
* Besides managing and drawing the list of drawables, this class serves two purposes:
* 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.
* (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.
*
* @hide
*/
@@ -85,6 +89,22 @@ class ViewOverlay extends ViewGroup implements Overlay {
@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]);
}
parent.removeView(child);
}
super.addView(child);
}
@@ -133,7 +153,6 @@ class ViewOverlay extends ViewGroup implements Overlay {
public void invalidate(Rect dirty) {
super.invalidate(dirty);
if (mHostView != null) {
dirty.offset(getLeft(), getTop());
mHostView.invalidate(dirty);
}
}
@@ -203,7 +222,15 @@ class ViewOverlay extends ViewGroup implements Overlay {
@Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
if (mHostView != null) {
mHostView.invalidate(dirty);
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;
}