Send cancel event to recycled views instead of an up.
Bug #2309387 This was a problem in lists with list items that would cause notifyDatasetChanged() interleaved with a series of up/down motion events. This is a pretty rare case but it's worth fixing it to avoid getting views in a weird state.
This commit is contained in:
@@ -1506,6 +1506,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
*/
|
||||
private static final int PREPRESSED = 0x02000000;
|
||||
|
||||
/**
|
||||
* Indicates whether the view is temporarily detached.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
|
||||
|
||||
/**
|
||||
* Always allow a user to overscroll this view, provided it is a
|
||||
* view that can scroll.
|
||||
@@ -3668,6 +3675,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
*/
|
||||
public void onStartTemporaryDetach() {
|
||||
removeUnsetPressCallback();
|
||||
mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5913,6 +5921,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
* @see #onAttachedToWindow()
|
||||
*/
|
||||
protected void onDetachedFromWindow() {
|
||||
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
|
||||
removeUnsetPressCallback();
|
||||
removeLongPressCallback();
|
||||
destroyDrawingCache();
|
||||
|
||||
@@ -859,6 +859,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
final float xc = scrolledXFloat - child.mLeft;
|
||||
final float yc = scrolledYFloat - child.mTop;
|
||||
ev.setLocation(xc, yc);
|
||||
child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
|
||||
if (child.dispatchTouchEvent(ev)) {
|
||||
// Event handled, we have a target now.
|
||||
mMotionTarget = child;
|
||||
@@ -889,6 +890,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
// We don't have a target, this means we're handling the
|
||||
// event as a regular view.
|
||||
ev.setLocation(xf, yf);
|
||||
if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
|
||||
ev.setAction(MotionEvent.ACTION_CANCEL);
|
||||
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
|
||||
}
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
@@ -897,6 +902,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
if (!disallowIntercept && onInterceptTouchEvent(ev)) {
|
||||
final float xc = scrolledXFloat - (float) target.mLeft;
|
||||
final float yc = scrolledYFloat - (float) target.mTop;
|
||||
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
|
||||
ev.setAction(MotionEvent.ACTION_CANCEL);
|
||||
ev.setLocation(xc, yc);
|
||||
if (!target.dispatchTouchEvent(ev)) {
|
||||
@@ -921,6 +927,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
final float yc = scrolledYFloat - (float) target.mTop;
|
||||
ev.setLocation(xc, yc);
|
||||
|
||||
if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
|
||||
ev.setAction(MotionEvent.ACTION_CANCEL);
|
||||
target.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
|
||||
mMotionTarget = null;
|
||||
}
|
||||
|
||||
return target.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user