am f1792c42: Merge "Fix hotspot coordinate propagation in ViewGroup and AbsListView" into lmp-mr1-dev
* commit 'f1792c4219fb341a59c4b90c0ce5dd6e0e7b87f0': Fix hotspot coordinate propagation in ViewGroup and AbsListView
This commit is contained in:
@@ -33331,6 +33331,7 @@ package android.view {
|
||||
method public void dispatchDisplayHint(int);
|
||||
method public boolean dispatchDragEvent(android.view.DragEvent);
|
||||
method protected void dispatchDraw(android.graphics.Canvas);
|
||||
method public void dispatchDrawableHotspotChanged(float, float);
|
||||
method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
|
||||
method public boolean dispatchGenericMotionEvent(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
|
||||
* 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>
|
||||
* 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) {
|
||||
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
|
||||
private PointF mLocalPoint;
|
||||
|
||||
// Lazily-created holder for point computations.
|
||||
private float[] mTempPoint;
|
||||
|
||||
// Layout animation
|
||||
private LayoutAnimationController mLayoutAnimationController;
|
||||
private Animation.AnimationListener mAnimationListener;
|
||||
@@ -2442,6 +2445,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
|| 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
|
||||
* 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,
|
||||
PointF outLocalPoint) {
|
||||
float localX = x + mScrollX - child.mLeft;
|
||||
float localY = y + mScrollY - child.mTop;
|
||||
if (! child.hasIdentityMatrix() && mAttachInfo != null) {
|
||||
final float[] localXY = mAttachInfo.mTmpTransformLocation;
|
||||
localXY[0] = localX;
|
||||
localXY[1] = localY;
|
||||
child.getInverseMatrix().mapPoints(localXY);
|
||||
localX = localXY[0];
|
||||
localY = localXY[1];
|
||||
}
|
||||
final boolean isInView = child.pointInView(localX, localY);
|
||||
final float[] point = getTempPoint();
|
||||
point[0] = x;
|
||||
point[1] = y;
|
||||
transformPointToViewLocal(point, child);
|
||||
final boolean isInView = child.pointInView(point[0], point[1]);
|
||||
if (isInView && outLocalPoint != null) {
|
||||
outLocalPoint.set(localX, localY);
|
||||
outLocalPoint.set(point[0], point[1]);
|
||||
}
|
||||
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,
|
||||
* 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
|
||||
void 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
|
||||
protected int[] onCreateDrawableState(int extraSpace) {
|
||||
if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
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[] mScrollConsumed = new int[2];
|
||||
|
||||
private final float[] mTmpPoint = new float[2];
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
*/
|
||||
void positionSelectorLikeTouch(int position, View sel, float x, float y) {
|
||||
positionSelectorLikeFocus(position, sel);
|
||||
|
||||
if (mSelector != null && position != INVALID_POSITION) {
|
||||
mSelector.setHotspot(x, y);
|
||||
}
|
||||
positionSelector(position, sel, true, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Positions the selector in a way that mimics keyboard focus.
|
||||
*/
|
||||
void positionSelectorLikeFocus(int position, View sel) {
|
||||
// If we're changing position, update the visibility since the selector
|
||||
// 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) {
|
||||
if (mSelector != null && mSelectorPosition != position && position != INVALID_POSITION) {
|
||||
final Rect bounds = mSelectorRect;
|
||||
final float x = bounds.exactCenterX();
|
||||
final float y = bounds.exactCenterY();
|
||||
selector.setVisible(getVisibility() == VISIBLE, false);
|
||||
selector.setHotspot(x, y);
|
||||
positionSelector(position, sel, true, x, y);
|
||||
} else {
|
||||
positionSelector(position, 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) {
|
||||
mSelectorPosition = position;
|
||||
}
|
||||
@@ -2560,7 +2554,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
// Update the selector drawable.
|
||||
final Drawable selector = mSelector;
|
||||
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);
|
||||
if (positionChanged) {
|
||||
if (getVisibility() == VISIBLE) {
|
||||
selector.setVisible(true, false);
|
||||
}
|
||||
selector.setState(getDrawableState());
|
||||
}
|
||||
if (manageHotspot) {
|
||||
selector.setHotspot(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
@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.
|
||||
*
|
||||
@@ -3256,6 +3271,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
mLayoutMode = LAYOUT_NORMAL;
|
||||
|
||||
if (!mDataChanged) {
|
||||
final float[] point = mTmpPoint;
|
||||
point[0] = x;
|
||||
point[1] = y;
|
||||
transformPointToViewLocal(point, child);
|
||||
child.drawableHotspotChanged(point[0], point[1]);
|
||||
child.setPressed(true);
|
||||
setPressed(true);
|
||||
layoutChildren();
|
||||
@@ -3756,10 +3776,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
}
|
||||
// Otherwise, check containment within list bounds. If we're
|
||||
// outside bounds, cancel any active presses.
|
||||
final View motionView = getChildAt(mMotionPosition - mFirstPosition);
|
||||
final float x = ev.getX(pointerIndex);
|
||||
if (!pointInView(x, y, mTouchSlop)) {
|
||||
setPressed(false);
|
||||
final View motionView = getChildAt(mMotionPosition - mFirstPosition);
|
||||
if (motionView != null) {
|
||||
motionView.setPressed(false);
|
||||
}
|
||||
@@ -3767,6 +3787,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
mPendingCheckForTap : mPendingCheckForLongPress);
|
||||
mTouchMode = TOUCH_MODE_DONE_WAITING;
|
||||
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;
|
||||
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.
|
||||
// However, we will NOT place them into scrap views.
|
||||
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) {
|
||||
mRipple.cancel();
|
||||
mRipple = null;
|
||||
mRippleActive = false;
|
||||
}
|
||||
|
||||
if (mBackground != null) {
|
||||
mBackground.cancel();
|
||||
mBackground = null;
|
||||
mBackgroundActive = false;
|
||||
}
|
||||
|
||||
cancelExitingRipples();
|
||||
|
||||
Reference in New Issue
Block a user