diff options
author | Mindy Pereira <mindyp@google.com> | 2013-09-03 17:38:36 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-09-03 17:38:36 +0000 |
commit | 510caf30d2f7b240ee0cb470f52299af8576ea8d (patch) | |
tree | 28666760b686839100fd146fe5db461234216b2e /core/java | |
parent | 3f8da09136087bd4f97c1e13e2fb7f8cfb81941c (diff) | |
parent | e8ce8ba2b5633e479ccaa82d8e3147ccbba62961 (diff) | |
download | frameworks_base-510caf30d2f7b240ee0cb470f52299af8576ea8d.zip frameworks_base-510caf30d2f7b240ee0cb470f52299af8576ea8d.tar.gz frameworks_base-510caf30d2f7b240ee0cb470f52299af8576ea8d.tar.bz2 |
Merge "Add doubletap swipe to scalegesturedetector" into klp-dev
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/view/ScaleGestureDetector.java | 132 |
1 files changed, 119 insertions, 13 deletions
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index 51c5c7b..0bebc04 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -18,6 +18,8 @@ package android.view; import android.content.Context; import android.content.res.Resources; +import android.os.Build; +import android.os.Handler; import android.os.SystemClock; import android.util.FloatMath; @@ -128,6 +130,8 @@ public class ScaleGestureDetector { private float mFocusX; private float mFocusY; + private boolean mDoubleTapScales; + private float mCurrSpan; private float mPrevSpan; private float mInitialSpan; @@ -148,9 +152,14 @@ public class ScaleGestureDetector { private int mTouchHistoryDirection; private long mTouchHistoryLastAcceptedTime; private int mTouchMinMajor; + private MotionEvent mDoubleTapEvent; + private int mDoubleTapMode = DOUBLE_TAP_MODE_NONE; + private final Handler mHandler; private static final long TOUCH_STABILIZE_TIME = 128; // ms - private static final int TOUCH_MIN_MAJOR = 48; // dp + private static final int DOUBLE_TAP_MODE_NONE = 0; + private static final int DOUBLE_TAP_MODE_IN_PROGRESS = 1; + /** * Consistency verifier for debugging purposes. @@ -158,8 +167,37 @@ public class ScaleGestureDetector { private final InputEventConsistencyVerifier mInputEventConsistencyVerifier = InputEventConsistencyVerifier.isInstrumentationEnabled() ? new InputEventConsistencyVerifier(this, 0) : null; + private GestureDetector mGestureDetector; + + private boolean mEventBeforeOrAboveStartingGestureEvent; + /** + * Creates a ScaleGestureDetector with the supplied listener. + * You may only use this constructor from a {@link android.os.Looper Looper} thread. + * + * @param context the application's context + * @param listener the listener invoked for all the callbacks, this must + * not be null. + * + * @throws NullPointerException if {@code listener} is null. + */ public ScaleGestureDetector(Context context, OnScaleGestureListener listener) { + this(context, listener, null); + } + + /** + * Creates a ScaleGestureDetector with the supplied listener. + * @see android.os.Handler#Handler() + * + * @param context the application's context + * @param listener the listener invoked for all the callbacks, this must + * not be null. + * @param handler the handler to use for running deferred listener events. + * + * @throws NullPointerException if {@code listener} is null. + */ + public ScaleGestureDetector(Context context, OnScaleGestureListener listener, + Handler handler) { mContext = context; mListener = listener; mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2; @@ -167,8 +205,12 @@ public class ScaleGestureDetector { final Resources res = context.getResources(); mTouchMinMajor = res.getDimensionPixelSize( com.android.internal.R.dimen.config_minScalingTouchMajor); - mMinSpan = res.getDimensionPixelSize( - com.android.internal.R.dimen.config_minScalingSpan); + mMinSpan = res.getDimensionPixelSize(com.android.internal.R.dimen.config_minScalingSpan); + mHandler = handler; + // Quick scale is enabled by default after JB_MR2 + if (context.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.JELLY_BEAN_MR2) { + setQuickScaleEnabled(true); + } } /** @@ -263,8 +305,14 @@ public class ScaleGestureDetector { final int action = event.getActionMasked(); + // Forward the event to check for double tap gesture + if (mDoubleTapScales) { + mGestureDetector.onTouchEvent(event); + } + final boolean streamComplete = action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL; + if (action == MotionEvent.ACTION_DOWN || streamComplete) { // Reset any scale in progress with the listener. // If it's an ACTION_DOWN we're beginning a new event stream. @@ -273,6 +321,7 @@ public class ScaleGestureDetector { mListener.onScaleEnd(this); mInProgress = false; mInitialSpan = 0; + mDoubleTapMode = DOUBLE_TAP_MODE_NONE; } if (streamComplete) { @@ -284,21 +333,37 @@ public class ScaleGestureDetector { final boolean configChanged = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN; + + final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP; final int skipIndex = pointerUp ? event.getActionIndex() : -1; // Determine focal point float sumX = 0, sumY = 0; final int count = event.getPointerCount(); - for (int i = 0; i < count; i++) { - if (skipIndex == i) continue; - sumX += event.getX(i); - sumY += event.getY(i); - } final int div = pointerUp ? count - 1 : count; - final float focusX = sumX / div; - final float focusY = sumY / div; + final float focusX; + final float focusY; + if (mDoubleTapMode == DOUBLE_TAP_MODE_IN_PROGRESS) { + // In double tap mode, the focal pt is always where the double tap + // gesture started + focusX = mDoubleTapEvent.getX(); + focusY = mDoubleTapEvent.getY(); + if (event.getY() < focusY) { + mEventBeforeOrAboveStartingGestureEvent = true; + } else { + mEventBeforeOrAboveStartingGestureEvent = false; + } + } else { + for (int i = 0; i < count; i++) { + if (skipIndex == i) continue; + sumX += event.getX(i); + sumY += event.getY(i); + } + focusX = sumX / div; + focusY = sumY / div; + } addTouchHistory(event); @@ -320,7 +385,12 @@ public class ScaleGestureDetector { // the focal point. final float spanX = devX * 2; final float spanY = devY * 2; - final float span = FloatMath.sqrt(spanX * spanX + spanY * spanY); + final float span; + if (inDoubleTapMode()) { + span = spanY; + } else { + span = FloatMath.sqrt(spanX * spanX + spanY * spanY); + } // Dispatch begin/end events as needed. // If the configuration changes, notify the app to reset its current state by beginning @@ -328,10 +398,11 @@ public class ScaleGestureDetector { final boolean wasInProgress = mInProgress; mFocusX = focusX; mFocusY = focusY; - if (mInProgress && (span < mMinSpan || configChanged)) { + if (!inDoubleTapMode() && mInProgress && (span < mMinSpan || configChanged)) { mListener.onScaleEnd(this); mInProgress = false; mInitialSpan = span; + mDoubleTapMode = DOUBLE_TAP_MODE_NONE; } if (configChanged) { mPrevSpanX = mCurrSpanX = spanX; @@ -354,6 +425,7 @@ public class ScaleGestureDetector { mCurrSpan = span; boolean updatePrev = true; + if (mInProgress) { updatePrev = mListener.onScale(this); } @@ -369,6 +441,34 @@ public class ScaleGestureDetector { return true; } + + private boolean inDoubleTapMode() { + return mDoubleTapMode == DOUBLE_TAP_MODE_IN_PROGRESS; + } + + /** + * Set whether the associated {@link OnScaleGestureListener} should receive onScale callbacks + * when the user performs a doubleTap followed by a swipe. Note that this is enabled by default + * if the app targets API 19 and newer. + * @param scales true to enable quick scaling, false to disable + */ + public void setQuickScaleEnabled(boolean scales) { + mDoubleTapScales = scales; + if (mDoubleTapScales && mGestureDetector == null) { + GestureDetector.SimpleOnGestureListener gestureListener = + new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onDoubleTap(MotionEvent e) { + // Double tap: start watching for a swipe + mDoubleTapEvent = e; + mDoubleTapMode = DOUBLE_TAP_MODE_IN_PROGRESS; + return true; + } + }; + mGestureDetector = new GestureDetector(mContext, gestureListener, mHandler); + } + } + /** * Returns {@code true} if a scale gesture is in progress. */ @@ -472,6 +572,12 @@ public class ScaleGestureDetector { * @return The current scaling factor. */ public float getScaleFactor() { + if (inDoubleTapMode() && mEventBeforeOrAboveStartingGestureEvent) { + // Drag is moving up; the further away from the gesture + // start, the smaller the span should be, the closer, + // the larger the span, and therefore the larger the scale + return (1 / mCurrSpan) / (1 / mPrevSpan); + } return mPrevSpan > 0 ? mCurrSpan / mPrevSpan : 1; } @@ -493,4 +599,4 @@ public class ScaleGestureDetector { public long getEventTime() { return mCurrTime; } -} +}
\ No newline at end of file |