summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Viverette <alanv@google.com>2013-08-26 20:48:58 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-08-26 20:48:59 +0000
commit9212e350d52ea98cb673280870c54319b03ccad3 (patch)
tree78ea80c8ac8ecf0c64909d69702310ae9f6fbc52
parent3871fdb966846d9026500696e48ccc64349eedb4 (diff)
parent69960142efa8d228adbfcbabdcf618426e31e1f5 (diff)
downloadframeworks_base-9212e350d52ea98cb673280870c54319b03ccad3.zip
frameworks_base-9212e350d52ea98cb673280870c54319b03ccad3.tar.gz
frameworks_base-9212e350d52ea98cb673280870c54319b03ccad3.tar.bz2
Merge "Reconcile drag-to-open and touch event interception" into klp-dev
-rw-r--r--core/java/android/widget/ListPopupWindow.java101
-rw-r--r--core/java/android/widget/Spinner.java2
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuPresenter.java2
3 files changed, 79 insertions, 26 deletions
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 8919248..3e1947c 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -32,6 +32,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.MeasureSpec;
+import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
@@ -1133,18 +1134,32 @@ public class ListPopupWindow {
*
* @hide
*/
- public static abstract class ForwardingListener implements View.OnTouchListener {
+ public static abstract class ForwardingListener
+ implements View.OnTouchListener, View.OnAttachStateChangeListener {
/** Scaled touch slop, used for detecting movement outside bounds. */
private final float mScaledTouchSlop;
+ /** Timeout before disallowing intercept on the source's parent. */
+ private final int mTapTimeout;
+
+ /** Source view from which events are forwarded. */
+ private final View mSrc;
+
+ /** Runnable used to prevent conflicts with scrolling parents. */
+ private Runnable mDisallowIntercept;
+
/** Whether this listener is currently forwarding touch events. */
private boolean mForwarding;
/** The id of the first pointer down in the current event stream. */
private int mActivePointerId;
- public ForwardingListener(Context context) {
- mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ public ForwardingListener(View src) {
+ mSrc = src;
+ mScaledTouchSlop = ViewConfiguration.get(src.getContext()).getScaledTouchSlop();
+ mTapTimeout = ViewConfiguration.getTapTimeout();
+
+ src.addOnAttachStateChangeListener(this);
}
/**
@@ -1164,15 +1179,29 @@ public class ListPopupWindow {
final boolean wasForwarding = mForwarding;
final boolean forwarding;
if (wasForwarding) {
- forwarding = onTouchForwarded(v, event) || !onForwardingStopped();
+ forwarding = onTouchForwarded(event) || !onForwardingStopped();
} else {
- forwarding = onTouchObserved(v, event) && onForwardingStarted();
+ forwarding = onTouchObserved(event) && onForwardingStarted();
}
mForwarding = forwarding;
return forwarding || wasForwarding;
}
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ mForwarding = false;
+ mActivePointerId = MotionEvent.INVALID_POINTER_ID;
+
+ if (mDisallowIntercept != null) {
+ mSrc.removeCallbacks(mDisallowIntercept);
+ }
+ }
+
/**
* Called when forwarding would like to start.
* <p>
@@ -1182,7 +1211,7 @@ public class ListPopupWindow {
*
* @return true to start forwarding, false otherwise
*/
- public boolean onForwardingStarted() {
+ protected boolean onForwardingStarted() {
final ListPopupWindow popup = getPopup();
if (popup != null && !popup.isShowing()) {
popup.show();
@@ -1199,7 +1228,7 @@ public class ListPopupWindow {
*
* @return true to stop forwarding, false otherwise
*/
- public boolean onForwardingStopped() {
+ protected boolean onForwardingStopped() {
final ListPopupWindow popup = getPopup();
if (popup != null && popup.isShowing()) {
popup.dismiss();
@@ -1210,29 +1239,45 @@ public class ListPopupWindow {
/**
* Observes motion events and determines when to start forwarding.
*
- * @param src view from which the event originated
* @param srcEvent motion event in source view coordinates
* @return true to start forwarding motion events, false otherwise
*/
- private boolean onTouchObserved(View src, MotionEvent srcEvent) {
+ private boolean onTouchObserved(MotionEvent srcEvent) {
+ final View src = mSrc;
if (!src.isEnabled()) {
return false;
}
- // The first pointer down is always the active pointer.
final int actionMasked = srcEvent.getActionMasked();
- if (actionMasked == MotionEvent.ACTION_DOWN) {
- mActivePointerId = srcEvent.getPointerId(0);
- }
-
- final int activePointerIndex = srcEvent.findPointerIndex(mActivePointerId);
- if (activePointerIndex >= 0) {
- final float x = srcEvent.getX(activePointerIndex);
- final float y = srcEvent.getY(activePointerIndex);
- if (!src.pointInView(x, y, mScaledTouchSlop)) {
- // The pointer has moved outside of the view.
- return true;
- }
+ switch (actionMasked) {
+ case MotionEvent.ACTION_DOWN:
+ mActivePointerId = srcEvent.getPointerId(0);
+ if (mDisallowIntercept == null) {
+ mDisallowIntercept = new DisallowIntercept();
+ }
+ src.postDelayed(mDisallowIntercept, mTapTimeout);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ final int activePointerIndex = srcEvent.findPointerIndex(mActivePointerId);
+ if (activePointerIndex >= 0) {
+ final float x = srcEvent.getX(activePointerIndex);
+ final float y = srcEvent.getY(activePointerIndex);
+ if (!src.pointInView(x, y, mScaledTouchSlop)) {
+ // The pointer has moved outside of the view.
+ if (mDisallowIntercept != null) {
+ src.removeCallbacks(mDisallowIntercept);
+ }
+ src.getParent().requestDisallowInterceptTouchEvent(true);
+ return true;
+ }
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ if (mDisallowIntercept != null) {
+ src.removeCallbacks(mDisallowIntercept);
+ }
+ break;
}
return false;
@@ -1242,11 +1287,11 @@ public class ListPopupWindow {
* Handled forwarded motion events and determines when to stop
* forwarding.
*
- * @param src view from which the event originated
* @param srcEvent motion event in source view coordinates
* @return true to continue forwarding motion events, false to cancel
*/
- private boolean onTouchForwarded(View src, MotionEvent srcEvent) {
+ private boolean onTouchForwarded(MotionEvent srcEvent) {
+ final View src = mSrc;
final ListPopupWindow popup = getPopup();
if (popup == null || !popup.isShowing()) {
return false;
@@ -1267,6 +1312,14 @@ public class ListPopupWindow {
dstEvent.recycle();
return handled;
}
+
+ private class DisallowIntercept implements Runnable {
+ @Override
+ public void run() {
+ final ViewParent parent = mSrc.getParent();
+ parent.requestDisallowInterceptTouchEvent(true);
+ }
+ }
}
/**
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 7c7df96..2531aa6 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -198,7 +198,7 @@ public class Spinner extends AbsSpinner implements OnClickListener {
}
mPopup = popup;
- mForwardingListener = new ForwardingListener(context) {
+ mForwardingListener = new ForwardingListener(this) {
@Override
public ListPopupWindow getPopup() {
return popup;
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 5d0a603..a47712b 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -565,7 +565,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter
setVisibility(VISIBLE);
setEnabled(true);
- setOnTouchListener(new ForwardingListener(context) {
+ setOnTouchListener(new ForwardingListener(this) {
@Override
public ListPopupWindow getPopup() {
if (mOverflowPopup == null) {