Merge "Fix hotspot coordinate propagation in ViewGroup and AbsListView" into lmp-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f1792c4219
@@ -33331,6 +33331,7 @@ package android.view {
|
|||||||
method public void dispatchDisplayHint(int);
|
method public void dispatchDisplayHint(int);
|
||||||
method public boolean dispatchDragEvent(android.view.DragEvent);
|
method public boolean dispatchDragEvent(android.view.DragEvent);
|
||||||
method protected void dispatchDraw(android.graphics.Canvas);
|
method protected void dispatchDraw(android.graphics.Canvas);
|
||||||
|
method public void dispatchDrawableHotspotChanged(float, float);
|
||||||
method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
|
method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
|
||||||
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
|
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
|
||||||
method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
|
method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
|
||||||
|
|||||||
@@ -16059,7 +16059,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is called whenever the view hotspot changes and needs to
|
* This function is called whenever the view hotspot changes and needs to
|
||||||
* be propagated to drawables managed by the view.
|
* be propagated to drawables or child views managed by the view.
|
||||||
|
* <p>
|
||||||
|
* Dispatching to child views is handled by
|
||||||
|
* {@link #dispatchDrawableHotspotChanged(float, float)}.
|
||||||
* <p>
|
* <p>
|
||||||
* Be sure to call through to the superclass when overriding this function.
|
* Be sure to call through to the superclass when overriding this function.
|
||||||
*
|
*
|
||||||
@@ -16070,6 +16073,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
if (mBackground != null) {
|
if (mBackground != null) {
|
||||||
mBackground.setHotspot(x, y);
|
mBackground.setHotspot(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispatchDrawableHotspotChanged(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches drawableHotspotChanged to all of this View's children.
|
||||||
|
*
|
||||||
|
* @param x hotspot x coordinate
|
||||||
|
* @param y hotspot y coordinate
|
||||||
|
* @see #drawableHotspotChanged(float, float)
|
||||||
|
*/
|
||||||
|
public void dispatchDrawableHotspotChanged(float x, float y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -161,6 +161,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
|||||||
// Used during drag dispatch
|
// Used during drag dispatch
|
||||||
private PointF mLocalPoint;
|
private PointF mLocalPoint;
|
||||||
|
|
||||||
|
// Lazily-created holder for point computations.
|
||||||
|
private float[] mTempPoint;
|
||||||
|
|
||||||
// Layout animation
|
// Layout animation
|
||||||
private LayoutAnimationController mLayoutAnimationController;
|
private LayoutAnimationController mLayoutAnimationController;
|
||||||
private Animation.AnimationListener mAnimationListener;
|
private Animation.AnimationListener mAnimationListener;
|
||||||
@@ -2442,6 +2445,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
|||||||
|| child.getAnimation() != null;
|
|| child.getAnimation() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float[] getTempPoint() {
|
||||||
|
if (mTempPoint == null) {
|
||||||
|
mTempPoint = new float[2];
|
||||||
|
}
|
||||||
|
return mTempPoint;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a child view contains the specified point when transformed
|
* Returns true if a child view contains the specified point when transformed
|
||||||
* into its coordinate space.
|
* into its coordinate space.
|
||||||
@@ -2450,23 +2460,29 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
|||||||
*/
|
*/
|
||||||
protected boolean isTransformedTouchPointInView(float x, float y, View child,
|
protected boolean isTransformedTouchPointInView(float x, float y, View child,
|
||||||
PointF outLocalPoint) {
|
PointF outLocalPoint) {
|
||||||
float localX = x + mScrollX - child.mLeft;
|
final float[] point = getTempPoint();
|
||||||
float localY = y + mScrollY - child.mTop;
|
point[0] = x;
|
||||||
if (! child.hasIdentityMatrix() && mAttachInfo != null) {
|
point[1] = y;
|
||||||
final float[] localXY = mAttachInfo.mTmpTransformLocation;
|
transformPointToViewLocal(point, child);
|
||||||
localXY[0] = localX;
|
final boolean isInView = child.pointInView(point[0], point[1]);
|
||||||
localXY[1] = localY;
|
|
||||||
child.getInverseMatrix().mapPoints(localXY);
|
|
||||||
localX = localXY[0];
|
|
||||||
localY = localXY[1];
|
|
||||||
}
|
|
||||||
final boolean isInView = child.pointInView(localX, localY);
|
|
||||||
if (isInView && outLocalPoint != null) {
|
if (isInView && outLocalPoint != null) {
|
||||||
outLocalPoint.set(localX, localY);
|
outLocalPoint.set(point[0], point[1]);
|
||||||
}
|
}
|
||||||
return isInView;
|
return isInView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void transformPointToViewLocal(float[] point, View child) {
|
||||||
|
point[0] += mScrollX - child.mLeft;
|
||||||
|
point[1] += mScrollY - child.mTop;
|
||||||
|
|
||||||
|
if (!child.hasIdentityMatrix()) {
|
||||||
|
child.getInverseMatrix().mapPoints(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms a motion event into the coordinate space of a particular child view,
|
* Transforms a motion event into the coordinate space of a particular child view,
|
||||||
* filters out irrelevant pointer ids, and overrides its action if necessary.
|
* filters out irrelevant pointer ids, and overrides its action if necessary.
|
||||||
@@ -3606,6 +3622,44 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches drawable hotspot changes to child views that meet at least
|
||||||
|
* one of the following criteria:
|
||||||
|
* <ul>
|
||||||
|
* <li>Returns {@code false} from both {@link View#isClickable()} and
|
||||||
|
* {@link View#isLongClickable()}</li>
|
||||||
|
* <li>Requests duplication of parent state via
|
||||||
|
* {@link View#setDuplicateParentStateEnabled(boolean)}</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param x hotspot x coordinate
|
||||||
|
* @param y hotspot y coordinate
|
||||||
|
* @see #drawableHotspotChanged(float, float)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void dispatchDrawableHotspotChanged(float x, float y) {
|
||||||
|
final int count = mChildrenCount;
|
||||||
|
if (count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final View[] children = mChildren;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
final View child = children[i];
|
||||||
|
// Children that are clickable on their own should not
|
||||||
|
// receive hotspots when their parent view does.
|
||||||
|
final boolean nonActionable = !child.isClickable() && !child.isLongClickable();
|
||||||
|
final boolean duplicatesState = (child.mViewFlags & DUPLICATE_PARENT_STATE) != 0;
|
||||||
|
if (nonActionable || duplicatesState) {
|
||||||
|
final float[] point = getTempPoint();
|
||||||
|
point[0] = x;
|
||||||
|
point[1] = y;
|
||||||
|
transformPointToViewLocal(point, child);
|
||||||
|
child.drawableHotspotChanged(point[0], point[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void dispatchCancelPendingInputEvents() {
|
void dispatchCancelPendingInputEvents() {
|
||||||
super.dispatchCancelPendingInputEvents();
|
super.dispatchCancelPendingInputEvents();
|
||||||
@@ -5960,28 +6014,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void drawableHotspotChanged(float x, float y) {
|
|
||||||
super.drawableHotspotChanged(x, y);
|
|
||||||
|
|
||||||
if ((mGroupFlags & FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE) != 0) {
|
|
||||||
if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) {
|
|
||||||
throw new IllegalStateException("addStateFromChildren cannot be enabled if a"
|
|
||||||
+ " child has duplicateParentState set to true");
|
|
||||||
}
|
|
||||||
|
|
||||||
final View[] children = mChildren;
|
|
||||||
final int count = mChildrenCount;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
final View child = children[i];
|
|
||||||
if ((child.mViewFlags & DUPLICATE_PARENT_STATE) != 0) {
|
|
||||||
child.drawableHotspotChanged(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int[] onCreateDrawableState(int extraSpace) {
|
protected int[] onCreateDrawableState(int extraSpace) {
|
||||||
if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) {
|
if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.PointF;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.TransitionDrawable;
|
import android.graphics.drawable.TransitionDrawable;
|
||||||
@@ -611,6 +612,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
private final int[] mScrollOffset = new int[2];
|
private final int[] mScrollOffset = new int[2];
|
||||||
private final int[] mScrollConsumed = new int[2];
|
private final int[] mScrollConsumed = new int[2];
|
||||||
|
|
||||||
|
private final float[] mTmpPoint = new float[2];
|
||||||
|
|
||||||
// Used for offsetting MotionEvents that we feed to the VelocityTracker.
|
// Used for offsetting MotionEvents that we feed to the VelocityTracker.
|
||||||
// In the future it would be nice to be able to give this to the VelocityTracker
|
// In the future it would be nice to be able to give this to the VelocityTracker
|
||||||
// directly, or alternatively put a VT into absolute-positioning mode that only
|
// directly, or alternatively put a VT into absolute-positioning mode that only
|
||||||
@@ -2509,38 +2512,29 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
* Positions the selector in a way that mimics touch.
|
* Positions the selector in a way that mimics touch.
|
||||||
*/
|
*/
|
||||||
void positionSelectorLikeTouch(int position, View sel, float x, float y) {
|
void positionSelectorLikeTouch(int position, View sel, float x, float y) {
|
||||||
positionSelectorLikeFocus(position, sel);
|
positionSelector(position, sel, true, x, y);
|
||||||
|
|
||||||
if (mSelector != null && position != INVALID_POSITION) {
|
|
||||||
mSelector.setHotspot(x, y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Positions the selector in a way that mimics keyboard focus.
|
* Positions the selector in a way that mimics keyboard focus.
|
||||||
*/
|
*/
|
||||||
void positionSelectorLikeFocus(int position, View sel) {
|
void positionSelectorLikeFocus(int position, View sel) {
|
||||||
// If we're changing position, update the visibility since the selector
|
if (mSelector != null && mSelectorPosition != position && position != INVALID_POSITION) {
|
||||||
// is technically being detached from the previous selection.
|
|
||||||
final Drawable selector = mSelector;
|
|
||||||
final boolean manageState = selector != null && mSelectorPosition != position
|
|
||||||
&& position != INVALID_POSITION;
|
|
||||||
if (manageState) {
|
|
||||||
selector.setVisible(false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
positionSelector(position, sel);
|
|
||||||
|
|
||||||
if (manageState) {
|
|
||||||
final Rect bounds = mSelectorRect;
|
final Rect bounds = mSelectorRect;
|
||||||
final float x = bounds.exactCenterX();
|
final float x = bounds.exactCenterX();
|
||||||
final float y = bounds.exactCenterY();
|
final float y = bounds.exactCenterY();
|
||||||
selector.setVisible(getVisibility() == VISIBLE, false);
|
positionSelector(position, sel, true, x, y);
|
||||||
selector.setHotspot(x, y);
|
} else {
|
||||||
|
positionSelector(position, sel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void positionSelector(int position, View sel) {
|
void positionSelector(int position, View sel) {
|
||||||
|
positionSelector(position, sel, false, -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void positionSelector(int position, View sel, boolean manageHotspot, float x, float y) {
|
||||||
|
final boolean positionChanged = position != mSelectorPosition;
|
||||||
if (position != INVALID_POSITION) {
|
if (position != INVALID_POSITION) {
|
||||||
mSelectorPosition = position;
|
mSelectorPosition = position;
|
||||||
}
|
}
|
||||||
@@ -2560,7 +2554,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
// Update the selector drawable.
|
// Update the selector drawable.
|
||||||
final Drawable selector = mSelector;
|
final Drawable selector = mSelector;
|
||||||
if (selector != null) {
|
if (selector != null) {
|
||||||
|
if (positionChanged) {
|
||||||
|
// Wipe out the current selector state so that we can start
|
||||||
|
// over in the new position with a fresh state.
|
||||||
|
selector.setVisible(false, false);
|
||||||
|
selector.setState(StateSet.NOTHING);
|
||||||
|
}
|
||||||
selector.setBounds(selectorRect);
|
selector.setBounds(selectorRect);
|
||||||
|
if (positionChanged) {
|
||||||
|
if (getVisibility() == VISIBLE) {
|
||||||
|
selector.setVisible(true, false);
|
||||||
|
}
|
||||||
|
selector.setState(getDrawableState());
|
||||||
|
}
|
||||||
|
if (manageHotspot) {
|
||||||
|
selector.setHotspot(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean isChildViewEnabled = mIsChildViewEnabled;
|
final boolean isChildViewEnabled = mIsChildViewEnabled;
|
||||||
@@ -3198,6 +3207,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
// get the selector in the right state, but we don't want to press each child.
|
// get the selector in the right state, but we don't want to press each child.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispatchDrawableHotspotChanged(float x, float y) {
|
||||||
|
// Don't dispatch hotspot changes to children. We'll manually handle
|
||||||
|
// calling drawableHotspotChanged on the correct child.
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a point to a position in the list.
|
* Maps a point to a position in the list.
|
||||||
*
|
*
|
||||||
@@ -3256,6 +3271,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
mLayoutMode = LAYOUT_NORMAL;
|
mLayoutMode = LAYOUT_NORMAL;
|
||||||
|
|
||||||
if (!mDataChanged) {
|
if (!mDataChanged) {
|
||||||
|
final float[] point = mTmpPoint;
|
||||||
|
point[0] = x;
|
||||||
|
point[1] = y;
|
||||||
|
transformPointToViewLocal(point, child);
|
||||||
|
child.drawableHotspotChanged(point[0], point[1]);
|
||||||
child.setPressed(true);
|
child.setPressed(true);
|
||||||
setPressed(true);
|
setPressed(true);
|
||||||
layoutChildren();
|
layoutChildren();
|
||||||
@@ -3756,10 +3776,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
}
|
}
|
||||||
// Otherwise, check containment within list bounds. If we're
|
// Otherwise, check containment within list bounds. If we're
|
||||||
// outside bounds, cancel any active presses.
|
// outside bounds, cancel any active presses.
|
||||||
|
final View motionView = getChildAt(mMotionPosition - mFirstPosition);
|
||||||
final float x = ev.getX(pointerIndex);
|
final float x = ev.getX(pointerIndex);
|
||||||
if (!pointInView(x, y, mTouchSlop)) {
|
if (!pointInView(x, y, mTouchSlop)) {
|
||||||
setPressed(false);
|
setPressed(false);
|
||||||
final View motionView = getChildAt(mMotionPosition - mFirstPosition);
|
|
||||||
if (motionView != null) {
|
if (motionView != null) {
|
||||||
motionView.setPressed(false);
|
motionView.setPressed(false);
|
||||||
}
|
}
|
||||||
@@ -3767,6 +3787,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
mPendingCheckForTap : mPendingCheckForLongPress);
|
mPendingCheckForTap : mPendingCheckForLongPress);
|
||||||
mTouchMode = TOUCH_MODE_DONE_WAITING;
|
mTouchMode = TOUCH_MODE_DONE_WAITING;
|
||||||
updateSelectorState();
|
updateSelectorState();
|
||||||
|
} else if (motionView != null) {
|
||||||
|
// Still within bounds, update the hotspot.
|
||||||
|
final float[] point = mTmpPoint;
|
||||||
|
point[0] = x;
|
||||||
|
point[1] = y;
|
||||||
|
transformPointToViewLocal(point, motionView);
|
||||||
|
motionView.drawableHotspotChanged(point[0], point[1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOUCH_MODE_SCROLL:
|
case TOUCH_MODE_SCROLL:
|
||||||
@@ -6416,6 +6443,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
// Note: We do place AdapterView.ITEM_VIEW_TYPE_IGNORE in active views.
|
// Note: We do place AdapterView.ITEM_VIEW_TYPE_IGNORE in active views.
|
||||||
// However, we will NOT place them into scrap views.
|
// However, we will NOT place them into scrap views.
|
||||||
activeViews[i] = child;
|
activeViews[i] = child;
|
||||||
|
// Remember the position so that setupChild() doesn't reset state.
|
||||||
|
lp.scrappedFromPosition = firstActivePosition + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -556,11 +556,13 @@ public class RippleDrawable extends LayerDrawable {
|
|||||||
if (mRipple != null) {
|
if (mRipple != null) {
|
||||||
mRipple.cancel();
|
mRipple.cancel();
|
||||||
mRipple = null;
|
mRipple = null;
|
||||||
|
mRippleActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBackground != null) {
|
if (mBackground != null) {
|
||||||
mBackground.cancel();
|
mBackground.cancel();
|
||||||
mBackground = null;
|
mBackground = null;
|
||||||
|
mBackgroundActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelExitingRipples();
|
cancelExitingRipples();
|
||||||
|
|||||||
Reference in New Issue
Block a user