diff options
| author | 2014-07-24 03:20:55 +0000 | |
|---|---|---|
| committer | 2014-07-23 18:56:15 +0000 | |
| commit | ef7ebbdff12c25f033beecf151bf3661716fde13 (patch) | |
| tree | d2891c2d4c050a052c45f564ada8364f5a5ca912 | |
| parent | fd4354a9ee0a484fcd310618ec5ad3da3cb689ff (diff) | |
| parent | bca05f5ce7716b82f4b3d9221480a807aeb7ff15 (diff) | |
Merge "Allow medium-long-press to initiate drag-to-open menus" into lmp-dev
| -rw-r--r-- | core/java/android/widget/ListPopupWindow.java | 86 |
1 files changed, 78 insertions, 8 deletions
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index 84b213bd9b2a..af4644b37208 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -1186,15 +1186,27 @@ public class ListPopupWindow { /** Timeout before disallowing intercept on the source's parent. */ private final int mTapTimeout; + /** Timeout before accepting a long-press to start forwarding. */ + private final int mLongPressTimeout; + /** Source view from which events are forwarded. */ private final View mSrc; /** Runnable used to prevent conflicts with scrolling parents. */ private Runnable mDisallowIntercept; + /** Runnable used to trigger forwarding on long-press. */ + private Runnable mTriggerLongPress; + /** Whether this listener is currently forwarding touch events. */ private boolean mForwarding; + /** + * Whether forwarding was initiated by a long-press. If so, we won't + * force the window to dismiss when the touch stream ends. + */ + private boolean mWasLongPress; + /** The id of the first pointer down in the current event stream. */ private int mActivePointerId; @@ -1203,6 +1215,9 @@ public class ListPopupWindow { mScaledTouchSlop = ViewConfiguration.get(src.getContext()).getScaledTouchSlop(); mTapTimeout = ViewConfiguration.getTapTimeout(); + // Use a medium-press timeout. Halfway between tap and long-press. + mLongPressTimeout = (mTapTimeout + ViewConfiguration.getLongPressTimeout()) / 2; + src.addOnAttachStateChangeListener(this); } @@ -1223,7 +1238,14 @@ public class ListPopupWindow { final boolean wasForwarding = mForwarding; final boolean forwarding; if (wasForwarding) { - forwarding = onTouchForwarded(event) || !onForwardingStopped(); + if (mWasLongPress) { + // If we started forwarding as a result of a long-press, + // just silently stop forwarding events so that the window + // stays open. + forwarding = onTouchForwarded(event); + } else { + forwarding = onTouchForwarded(event) || !onForwardingStopped(); + } } else { forwarding = onTouchObserved(event) && onForwardingStarted(); @@ -1305,21 +1327,29 @@ public class ListPopupWindow { switch (actionMasked) { case MotionEvent.ACTION_DOWN: mActivePointerId = srcEvent.getPointerId(0); + mWasLongPress = false; + if (mDisallowIntercept == null) { mDisallowIntercept = new DisallowIntercept(); } src.postDelayed(mDisallowIntercept, mTapTimeout); + + if (mTriggerLongPress == null) { + mTriggerLongPress = new TriggerLongPress(); + } + src.postDelayed(mTriggerLongPress, mLongPressTimeout); 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); + + // Has the pointer has moved outside of the view? if (!src.pointInView(x, y, mScaledTouchSlop)) { - // The pointer has moved outside of the view. - if (mDisallowIntercept != null) { - src.removeCallbacks(mDisallowIntercept); - } + clearCallbacks(); + + // Don't let the parent intercept our events. src.getParent().requestDisallowInterceptTouchEvent(true); return true; } @@ -1327,15 +1357,48 @@ public class ListPopupWindow { break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: - if (mDisallowIntercept != null) { - src.removeCallbacks(mDisallowIntercept); - } + clearCallbacks(); break; } return false; } + private void clearCallbacks() { + if (mTriggerLongPress != null) { + mSrc.removeCallbacks(mTriggerLongPress); + } + + if (mDisallowIntercept != null) { + mSrc.removeCallbacks(mDisallowIntercept); + } + } + + private void onLongPress() { + clearCallbacks(); + + final View src = mSrc; + if (!src.isEnabled()) { + return; + } + + if (!onForwardingStarted()) { + return; + } + + // Don't let the parent intercept our events. + mSrc.getParent().requestDisallowInterceptTouchEvent(true); + + // Make sure we cancel any ongoing source event stream. + final long now = SystemClock.uptimeMillis(); + final MotionEvent e = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0); + mSrc.onTouchEvent(e); + e.recycle(); + + mForwarding = true; + mWasLongPress = true; + } + /** * Handled forwarded motion events and determines when to stop * forwarding. @@ -1379,6 +1442,13 @@ public class ListPopupWindow { parent.requestDisallowInterceptTouchEvent(true); } } + + private class TriggerLongPress implements Runnable { + @Override + public void run() { + onLongPress(); + } + } } /** |