diff options
author | Alan Viverette <alanv@google.com> | 2013-08-26 20:48:58 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-08-26 20:48:59 +0000 |
commit | 9212e350d52ea98cb673280870c54319b03ccad3 (patch) | |
tree | 78ea80c8ac8ecf0c64909d69702310ae9f6fbc52 | |
parent | 3871fdb966846d9026500696e48ccc64349eedb4 (diff) | |
parent | 69960142efa8d228adbfcbabdcf618426e31e1f5 (diff) | |
download | frameworks_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.java | 101 | ||||
-rw-r--r-- | core/java/android/widget/Spinner.java | 2 | ||||
-rw-r--r-- | core/java/com/android/internal/view/menu/ActionMenuPresenter.java | 2 |
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) { |