summaryrefslogtreecommitdiffstats
path: root/photoviewer
diff options
context:
space:
mode:
authorPaul Westbrook <pwestbro@google.com>2012-09-21 12:47:03 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2012-09-21 12:47:03 -0700
commit0abf6f3aba2cd790de84e16fcc661e16b62cee00 (patch)
treeb80857a810a8b004eb8b610738a9d425962866ca /photoviewer
parente02a7d708f11c3fe213d17a886eebe1131cd77f3 (diff)
parent29c041a3e41b93c7ffd8f29550df501f0b45ea02 (diff)
downloadandroid_frameworks_ex-0abf6f3aba2cd790de84e16fcc661e16b62cee00.tar.gz
android_frameworks_ex-0abf6f3aba2cd790de84e16fcc661e16b62cee00.tar.bz2
android_frameworks_ex-0abf6f3aba2cd790de84e16fcc661e16b62cee00.zip
am 29c041a3: am 88d18b9f: am 4054bd6d: Use gesture detector from support lib
* commit '29c041a3e41b93c7ffd8f29550df501f0b45ea02': Use gesture detector from support lib
Diffstat (limited to 'photoviewer')
-rw-r--r--photoviewer/src/com/android/ex/photo/views/GestureDetector.java656
-rw-r--r--photoviewer/src/com/android/ex/photo/views/PhotoView.java22
2 files changed, 8 insertions, 670 deletions
diff --git a/photoviewer/src/com/android/ex/photo/views/GestureDetector.java b/photoviewer/src/com/android/ex/photo/views/GestureDetector.java
deleted file mode 100644
index c117661..0000000
--- a/photoviewer/src/com/android/ex/photo/views/GestureDetector.java
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ex.photo.views;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Message;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-/**
- * Detects various gestures and events using the supplied {@link MotionEvent}s.
- * The {@link OnGestureListener} callback will notify users when a particular
- * motion event has occurred. This class should only be used with {@link MotionEvent}s
- * reported via touch (don't use for trackball events).
- *
- * To use this class:
- * <ul>
- * <li>Create an instance of the {@code GestureDetector} for your {@link View}
- * <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call
- * {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback
- * will be executed when the events occur.
- * </ul>
- */
-public class GestureDetector {
- /**
- * The listener that is used to notify when gestures occur.
- * If you want to listen for all the different gestures then implement
- * this interface. If you only want to listen for a subset it might
- * be easier to extend {@link SimpleOnGestureListener}.
- */
- public interface OnGestureListener {
-
- /**
- * Notified when a tap occurs with the down {@link MotionEvent}
- * that triggered it. This will be triggered immediately for
- * every down event. All other events should be preceded by this.
- *
- * @param e The down motion event.
- */
- boolean onDown(MotionEvent e);
-
- /**
- * The user has performed a down {@link MotionEvent} and not performed
- * a move or up yet. This event is commonly used to provide visual
- * feedback to the user to let them know that their action has been
- * recognized i.e. highlight an element.
- *
- * @param e The down motion event
- */
- void onShowPress(MotionEvent e);
-
- /**
- * Notified when a tap occurs with the up {@link MotionEvent}
- * that triggered it.
- *
- * @param e The up motion event that completed the first tap
- * @return true if the event is consumed, else false
- */
- boolean onSingleTapUp(MotionEvent e);
-
- /**
- * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the
- * current move {@link MotionEvent}. The distance in x and y is also supplied for
- * convenience.
- *
- * @param e1 The first down motion event that started the scrolling.
- * @param e2 The move motion event that triggered the current onScroll.
- * @param distanceX The distance along the X axis that has been scrolled since the last
- * call to onScroll. This is NOT the distance between {@code e1}
- * and {@code e2}.
- * @param distanceY The distance along the Y axis that has been scrolled since the last
- * call to onScroll. This is NOT the distance between {@code e1}
- * and {@code e2}.
- * @return true if the event is consumed, else false
- */
- boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
-
- /**
- * Notified when a long press occurs with the initial on down {@link MotionEvent}
- * that trigged it.
- *
- * @param e The initial on down motion event that started the longpress.
- */
- void onLongPress(MotionEvent e);
-
- /**
- * Notified of a fling event when it occurs with the initial on down {@link MotionEvent}
- * and the matching up {@link MotionEvent}. The calculated velocity is supplied along
- * the x and y axis in pixels per second.
- *
- * @param e1 The first down motion event that started the fling.
- * @param e2 The move motion event that triggered the current onFling.
- * @param velocityX The velocity of this fling measured in pixels per second
- * along the x axis.
- * @param velocityY The velocity of this fling measured in pixels per second
- * along the y axis.
- * @return true if the event is consumed, else false
- */
- boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
- }
-
- /**
- * The listener that is used to notify when a double-tap or a confirmed
- * single-tap occur.
- */
- public interface OnDoubleTapListener {
- /**
- * Notified when a single-tap occurs.
- * <p>
- * Unlike {@link OnGestureListener#onSingleTapUp(MotionEvent)}, this
- * will only be called after the detector is confident that the user's
- * first tap is not followed by a second tap leading to a double-tap
- * gesture.
- *
- * @param e The down motion event of the single-tap.
- * @return true if the event is consumed, else false
- */
- boolean onSingleTapConfirmed(MotionEvent e);
-
- /**
- * Notified when a double-tap occurs.
- *
- * @param e The down motion event of the first tap of the double-tap.
- * @return true if the event is consumed, else false
- */
- boolean onDoubleTap(MotionEvent e);
-
- /**
- * Notified when an event within a double-tap gesture occurs, including
- * the down, move, and up events.
- *
- * @param e The motion event that occurred during the double-tap gesture.
- * @return true if the event is consumed, else false
- */
- boolean onDoubleTapEvent(MotionEvent e);
- }
-
- /**
- * A convenience class to extend when you only want to listen for a subset
- * of all the gestures. This implements all methods in the
- * {@link OnGestureListener} and {@link OnDoubleTapListener} but does
- * nothing and return {@code false} for all applicable methods.
- */
- public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener {
- public boolean onSingleTapUp(MotionEvent e) {
- return false;
- }
-
- public void onLongPress(MotionEvent e) {
- }
-
- public boolean onScroll(MotionEvent e1, MotionEvent e2,
- float distanceX, float distanceY) {
- return false;
- }
-
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
- float velocityY) {
- return false;
- }
-
- public void onShowPress(MotionEvent e) {
- }
-
- public boolean onDown(MotionEvent e) {
- return false;
- }
-
- public boolean onDoubleTap(MotionEvent e) {
- return false;
- }
-
- public boolean onDoubleTapEvent(MotionEvent e) {
- return false;
- }
-
- public boolean onSingleTapConfirmed(MotionEvent e) {
- return false;
- }
- }
-
- private int mTouchSlopSquare;
- private int mDoubleTapTouchSlopSquare;
- private int mDoubleTapSlopSquare;
- private int mMinimumFlingVelocity;
- private int mMaximumFlingVelocity;
-
- private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();
- private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
- private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
-
- // constants for Message.what used by GestureHandler below
- private static final int SHOW_PRESS = 1;
- private static final int LONG_PRESS = 2;
- private static final int TAP = 3;
-
- private final Handler mHandler;
- private final OnGestureListener mListener;
- private OnDoubleTapListener mDoubleTapListener;
-
- private boolean mStillDown;
- private boolean mInLongPress;
- private boolean mAlwaysInTapRegion;
- private boolean mAlwaysInBiggerTapRegion;
-
- private MotionEvent mCurrentDownEvent;
- private MotionEvent mPreviousUpEvent;
-
- /**
- * True when the user is still touching for the second tap (down, move, and
- * up events). Can only be true if there is a double tap listener attached.
- */
- private boolean mIsDoubleTapping;
-
- private float mLastFocusX;
- private float mLastFocusY;
- private float mDownFocusX;
- private float mDownFocusY;
-
- private boolean mIsLongpressEnabled;
-
- /**
- * Determines speed during touch scrolling
- */
- private VelocityTracker mVelocityTracker;
-
- private class GestureHandler extends Handler {
- GestureHandler() {
- super();
- }
-
- GestureHandler(Handler handler) {
- super(handler.getLooper());
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case SHOW_PRESS:
- mListener.onShowPress(mCurrentDownEvent);
- break;
-
- case LONG_PRESS:
- dispatchLongPress();
- break;
-
- case TAP:
- // If the user's finger is still down, do not count it as a tap
- if (mDoubleTapListener != null && !mStillDown) {
- mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
- }
- break;
-
- default:
- throw new RuntimeException("Unknown message " + msg); //never
- }
- }
- }
-
- /**
- * Creates a GestureDetector with the supplied listener.
- * This variant of the constructor should be used from a non-UI thread
- * (as it allows specifying the Handler).
- *
- * @param listener the listener invoked for all the callbacks, this must
- * not be null.
- * @param handler the handler to use
- *
- * @throws NullPointerException if either {@code listener} or
- * {@code handler} is null.
- *
- * @deprecated Use {@link #GestureDetector(android.content.Context,
- * android.view.GestureDetector.OnGestureListener, android.os.Handler)} instead.
- */
- @Deprecated
- public GestureDetector(OnGestureListener listener, Handler handler) {
- this(null, listener, handler);
- }
-
- /**
- * Creates a GestureDetector with the supplied listener.
- * You may only use this constructor from a UI thread (this is the usual situation).
- * @see android.os.Handler#Handler()
- *
- * @param listener the listener invoked for all the callbacks, this must
- * not be null.
- *
- * @throws NullPointerException if {@code listener} is null.
- *
- * @deprecated Use {@link #GestureDetector(android.content.Context,
- * android.view.GestureDetector.OnGestureListener)} instead.
- */
- @Deprecated
- public GestureDetector(OnGestureListener listener) {
- this(null, listener, null);
- }
-
- /**
- * Creates a GestureDetector with the supplied listener.
- * You may only use this constructor from a UI thread (this is the usual situation).
- * @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.
- *
- * @throws NullPointerException if {@code listener} is null.
- */
- public GestureDetector(Context context, OnGestureListener listener) {
- this(context, listener, null);
- }
-
- /**
- * Creates a GestureDetector with the supplied listener.
- * You may only use this constructor from a UI thread (this is the usual situation).
- * @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
- *
- * @throws NullPointerException if {@code listener} is null.
- */
- public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
- if (handler != null) {
- mHandler = new GestureHandler(handler);
- } else {
- mHandler = new GestureHandler();
- }
- mListener = listener;
- if (listener instanceof OnDoubleTapListener) {
- setOnDoubleTapListener((OnDoubleTapListener) listener);
- }
- init(context);
- }
-
- /**
- * Creates a GestureDetector with the supplied listener.
- * You may only use this constructor from a UI thread (this is the usual situation).
- * @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
- *
- * @throws NullPointerException if {@code listener} is null.
- */
- public GestureDetector(Context context, OnGestureListener listener, Handler handler,
- boolean unused) {
- this(context, listener, handler);
- }
-
- private void init(Context context) {
- if (mListener == null) {
- throw new NullPointerException("OnGestureListener must not be null");
- }
- mIsLongpressEnabled = true;
-
- // Fallback to support pre-donuts releases
- int touchSlop, doubleTapSlop, doubleTapTouchSlop;
- final ViewConfiguration configuration = ViewConfiguration.get(context);
- touchSlop = configuration.getScaledTouchSlop();
- doubleTapTouchSlop = configuration.getScaledTouchSlop();
- doubleTapSlop = configuration.getScaledDoubleTapSlop();
- mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity();
- mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity();
- mTouchSlopSquare = touchSlop * touchSlop;
- mDoubleTapTouchSlopSquare = doubleTapTouchSlop * doubleTapTouchSlop;
- mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop;
- }
-
- /**
- * Sets the listener which will be called for double-tap and related
- * gestures.
- *
- * @param onDoubleTapListener the listener invoked for all the callbacks, or
- * null to stop listening for double-tap gestures.
- */
- public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener) {
- mDoubleTapListener = onDoubleTapListener;
- }
-
- /**
- * Set whether longpress is enabled, if this is enabled when a user
- * presses and holds down you get a longpress event and nothing further.
- * If it's disabled the user can press and hold down and then later
- * moved their finger and you will get scroll events. By default
- * longpress is enabled.
- *
- * @param isLongpressEnabled whether longpress should be enabled.
- */
- public void setIsLongpressEnabled(boolean isLongpressEnabled) {
- mIsLongpressEnabled = isLongpressEnabled;
- }
-
- /**
- * @return true if longpress is enabled, else false.
- */
- public boolean isLongpressEnabled() {
- return mIsLongpressEnabled;
- }
-
- /**
- * Analyzes the given motion event and if applicable triggers the
- * appropriate callbacks on the {@link OnGestureListener} supplied.
- *
- * @param ev The current motion event.
- * @return true if the {@link OnGestureListener} consumed the event,
- * else false.
- */
- public boolean onTouchEvent(MotionEvent ev) {
- final int action = ev.getAction();
-
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
-
- final boolean pointerUp =
- (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP;
- final int skipIndex = pointerUp ? ev.getActionIndex() : -1;
-
- // Determine focal point
- float sumX = 0, sumY = 0;
- final int count = ev.getPointerCount();
- for (int i = 0; i < count; i++) {
- if (skipIndex == i) continue;
- sumX += ev.getX(i);
- sumY += ev.getY(i);
- }
- final int div = pointerUp ? count - 1 : count;
- final float focusX = sumX / div;
- final float focusY = sumY / div;
-
- boolean handled = false;
-
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_POINTER_DOWN:
- mDownFocusX = mLastFocusX = focusX;
- mDownFocusY = mLastFocusY = focusY;
- // Cancel long press and taps
- cancelTaps();
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- mDownFocusX = mLastFocusX = focusX;
- mDownFocusY = mLastFocusY = focusY;
-
- // Check the dot product of current velocities.
- // If the pointer that left was opposing another velocity vector, clear.
- mVelocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
- final int upIndex = ev.getActionIndex();
- final int id1 = ev.getPointerId(upIndex);
- final float x1 = mVelocityTracker.getXVelocity(id1);
- final float y1 = mVelocityTracker.getYVelocity(id1);
- for (int i = 0; i < count; i++) {
- if (i == upIndex) continue;
-
- final int id2 = ev.getPointerId(i);
- final float x = x1 * mVelocityTracker.getXVelocity(id2);
- final float y = y1 * mVelocityTracker.getYVelocity(id2);
-
- final float dot = x + y;
- if (dot < 0) {
- mVelocityTracker.clear();
- break;
- }
- }
- break;
-
- case MotionEvent.ACTION_DOWN:
- if (mDoubleTapListener != null) {
- boolean hadTapMessage = mHandler.hasMessages(TAP);
- if (hadTapMessage) mHandler.removeMessages(TAP);
- if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage &&
- isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) {
- // This is a second tap
- mIsDoubleTapping = true;
- // Give a callback with the first tap of the double-tap
- handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
- // Give a callback with down event of the double-tap
- handled |= mDoubleTapListener.onDoubleTapEvent(ev);
- } else {
- // This is a first tap
- mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
- }
- }
-
- mDownFocusX = mLastFocusX = focusX;
- mDownFocusY = mLastFocusY = focusY;
- if (mCurrentDownEvent != null) {
- mCurrentDownEvent.recycle();
- }
- mCurrentDownEvent = MotionEvent.obtain(ev);
- mAlwaysInTapRegion = true;
- mAlwaysInBiggerTapRegion = true;
- mStillDown = true;
- mInLongPress = false;
-
- if (mIsLongpressEnabled) {
- mHandler.removeMessages(LONG_PRESS);
- mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime()
- + TAP_TIMEOUT + LONGPRESS_TIMEOUT);
- }
- mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT);
- handled |= mListener.onDown(ev);
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (mInLongPress) {
- break;
- }
- final float scrollX = mLastFocusX - focusX;
- final float scrollY = mLastFocusY - focusY;
- if (mIsDoubleTapping) {
- // Give the move events of the double-tap
- handled |= mDoubleTapListener.onDoubleTapEvent(ev);
- } else if (mAlwaysInTapRegion) {
- final int deltaX = (int) (focusX - mDownFocusX);
- final int deltaY = (int) (focusY - mDownFocusY);
- int distance = (deltaX * deltaX) + (deltaY * deltaY);
- if (distance > mTouchSlopSquare) {
- handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
- mLastFocusX = focusX;
- mLastFocusY = focusY;
- mAlwaysInTapRegion = false;
- mHandler.removeMessages(TAP);
- mHandler.removeMessages(SHOW_PRESS);
- mHandler.removeMessages(LONG_PRESS);
- }
- if (distance > mDoubleTapTouchSlopSquare) {
- mAlwaysInBiggerTapRegion = false;
- }
- } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) {
- handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
- mLastFocusX = focusX;
- mLastFocusY = focusY;
- }
- break;
-
- case MotionEvent.ACTION_UP:
- mStillDown = false;
- MotionEvent currentUpEvent = MotionEvent.obtain(ev);
- if (mIsDoubleTapping) {
- // Finally, give the up event of the double-tap
- handled |= mDoubleTapListener.onDoubleTapEvent(ev);
- } else if (mInLongPress) {
- mHandler.removeMessages(TAP);
- mInLongPress = false;
- } else if (mAlwaysInTapRegion) {
- handled = mListener.onSingleTapUp(ev);
- } else {
-
- // A fling must travel the minimum tap distance
- final VelocityTracker velocityTracker = mVelocityTracker;
- final int pointerId = ev.getPointerId(0);
- velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
- final float velocityY = velocityTracker.getYVelocity(pointerId);
- final float velocityX = velocityTracker.getXVelocity(pointerId);
-
- if ((Math.abs(velocityY) > mMinimumFlingVelocity)
- || (Math.abs(velocityX) > mMinimumFlingVelocity)){
- handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY);
- }
- }
- if (mPreviousUpEvent != null) {
- mPreviousUpEvent.recycle();
- }
- // Hold the event we obtained above - listeners may have changed the original.
- mPreviousUpEvent = currentUpEvent;
- if (mVelocityTracker != null) {
- // This may have been cleared when we called out to the
- // application above.
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- mIsDoubleTapping = false;
- mHandler.removeMessages(SHOW_PRESS);
- mHandler.removeMessages(LONG_PRESS);
- break;
-
- case MotionEvent.ACTION_CANCEL:
- cancel();
- break;
- }
-
- return handled;
- }
-
- private void cancel() {
- mHandler.removeMessages(SHOW_PRESS);
- mHandler.removeMessages(LONG_PRESS);
- mHandler.removeMessages(TAP);
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mIsDoubleTapping = false;
- mStillDown = false;
- mAlwaysInTapRegion = false;
- mAlwaysInBiggerTapRegion = false;
- if (mInLongPress) {
- mInLongPress = false;
- }
- }
-
- private void cancelTaps() {
- mHandler.removeMessages(SHOW_PRESS);
- mHandler.removeMessages(LONG_PRESS);
- mHandler.removeMessages(TAP);
- mIsDoubleTapping = false;
- mAlwaysInTapRegion = false;
- mAlwaysInBiggerTapRegion = false;
- if (mInLongPress) {
- mInLongPress = false;
- }
- }
-
- private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
- MotionEvent secondDown) {
- if (!mAlwaysInBiggerTapRegion) {
- return false;
- }
-
- if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIMEOUT) {
- return false;
- }
-
- int deltaX = (int) firstDown.getX() - (int) secondDown.getX();
- int deltaY = (int) firstDown.getY() - (int) secondDown.getY();
- return (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare);
- }
-
- private void dispatchLongPress() {
- mHandler.removeMessages(TAP);
- mInLongPress = true;
- mListener.onLongPress(mCurrentDownEvent);
- }
-}
diff --git a/photoviewer/src/com/android/ex/photo/views/PhotoView.java b/photoviewer/src/com/android/ex/photo/views/PhotoView.java
index f697e1d..838a60d 100644
--- a/photoviewer/src/com/android/ex/photo/views/PhotoView.java
+++ b/photoviewer/src/com/android/ex/photo/views/PhotoView.java
@@ -28,7 +28,10 @@ import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
+import android.support.v4.view.GestureDetectorCompat;
import android.util.AttributeSet;
+import android.view.GestureDetector.OnGestureListener;
+import android.view.GestureDetector.OnDoubleTapListener;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
@@ -39,8 +42,8 @@ import com.android.ex.photo.fragments.PhotoViewFragment.HorizontallyScrollable;
/**
* Layout for the photo list view header.
*/
-public class PhotoView extends View implements GestureDetector.OnGestureListener,
- GestureDetector.OnDoubleTapListener, ScaleGestureDetector.OnScaleGestureListener,
+public class PhotoView extends View implements OnGestureListener,
+ OnDoubleTapListener, ScaleGestureDetector.OnScaleGestureListener,
HorizontallyScrollable {
/** Zoom animation duration; in milliseconds */
private final static long ZOOM_ANIMATION_DURATION = 300L;
@@ -109,7 +112,7 @@ public class PhotoView extends View implements GestureDetector.OnGestureListener
private float mMaxInitialScaleFactor;
/** Gesture detector */
- private GestureDetector mGestureDetector;
+ private GestureDetectorCompat mGestureDetector;
/** Gesture detector that detects pinch gestures */
private ScaleGestureDetector mScaleGetureDetector;
/** An external click listener */
@@ -130,8 +133,6 @@ public class PhotoView extends View implements GestureDetector.OnGestureListener
private float mMinScale;
/** Maximum scale to limit scaling to, 0 means no limit. */
private float mMaxScale;
- /** When {@code true}, prevents scale end gesture from falsely triggering a fling. */
- private boolean mFlingDebounce;
// To support translation [i.e. panning]
/** Runnable that can move the image */
@@ -260,10 +261,7 @@ public class PhotoView extends View implements GestureDetector.OnGestureListener
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (mTransformsEnabled) {
- if (!mFlingDebounce) {
- mTranslateRunnable.start(velocityX, velocityY);
- }
- mFlingDebounce = false;
+ mTranslateRunnable.start(velocityX, velocityY);
}
return true;
}
@@ -294,7 +292,6 @@ public class PhotoView extends View implements GestureDetector.OnGestureListener
mDoubleTapDebounce = true;
resetTransformations();
}
- mFlingDebounce = true;
}
@Override
@@ -940,12 +937,9 @@ public class PhotoView extends View implements GestureDetector.OnGestureListener
sCropPaint.setColor(resources.getColor(R.color.photo_crop_highlight_color));
sCropPaint.setStyle(Style.STROKE);
sCropPaint.setStrokeWidth(resources.getDimension(R.dimen.photo_crop_stroke_width));
-
- sHasMultitouchDistinct = context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
}
- mGestureDetector = new GestureDetector(context, this, null, !sHasMultitouchDistinct);
+ mGestureDetector = new GestureDetectorCompat(context, this, null);
mScaleGetureDetector = new ScaleGestureDetector(context, this);
mScaleRunnable = new ScaleRunnable(this);
mTranslateRunnable = new TranslateRunnable(this);