Blame client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/utils/GestureDetector.java

Packit Service fa4841
/*
Packit Service fa4841
 * Copyright (C) 2008 The Android Open Source Project
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *      http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 *
Packit Service fa4841
 * Modified for aFreeRDP by Martin Fleisz (martin.fleisz@thincast.com)
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
package com.freerdp.freerdpcore.utils;
Packit Service fa4841
Packit Service fa4841
import android.content.Context;
Packit Service fa4841
import android.os.Build;
Packit Service fa4841
import android.os.Handler;
Packit Service fa4841
import android.os.Message;
Packit Service fa4841
import android.util.DisplayMetrics;
Packit Service fa4841
import android.view.MotionEvent;
Packit Service fa4841
import android.view.ViewConfiguration;
Packit Service fa4841
Packit Service fa4841
public class GestureDetector
Packit Service fa4841
{
Packit Service fa4841
Packit Service fa4841
	private static final int TAP_TIMEOUT = 100;
Packit Service fa4841
	private static final int DOUBLE_TAP_TIMEOUT = 200;
Packit Service fa4841
	// Distance a touch can wander before we think the user is the first touch in a sequence of
Packit Service fa4841
	// double tap
Packit Service fa4841
	private static final int LARGE_TOUCH_SLOP = 18;
Packit Service fa4841
	// Distance between the first touch and second touch to still be considered a double tap
Packit Service fa4841
	private static final int DOUBLE_TAP_SLOP = 100;
Packit Service fa4841
	// constants for Message.what used by GestureHandler below
Packit Service fa4841
	private static final int SHOW_PRESS = 1;
Packit Service fa4841
	private static final int LONG_PRESS = 2;
Packit Service fa4841
	private static final int TAP = 3;
Packit Service fa4841
	private final Handler mHandler;
Packit Service fa4841
	private final OnGestureListener mListener;
Packit Service fa4841
	private int mTouchSlopSquare;
Packit Service fa4841
	private int mLargeTouchSlopSquare;
Packit Service fa4841
	private int mDoubleTapSlopSquare;
Packit Service fa4841
	private int mLongpressTimeout = 100;
Packit Service fa4841
	private OnDoubleTapListener mDoubleTapListener;
Packit Service fa4841
	private boolean mStillDown;
Packit Service fa4841
	private boolean mInLongPress;
Packit Service fa4841
	private boolean mAlwaysInTapRegion;
Packit Service fa4841
	private boolean mAlwaysInBiggerTapRegion;
Packit Service fa4841
	private MotionEvent mCurrentDownEvent;
Packit Service fa4841
	private MotionEvent mPreviousUpEvent;
Packit Service fa4841
	/**
Packit Service fa4841
	 * True when the user is still touching for the second tap (down, move, and
Packit Service fa4841
	 * up events). Can only be true if there is a double tap listener attached.
Packit Service fa4841
	 */
Packit Service fa4841
	private boolean mIsDoubleTapping;
Packit Service fa4841
	private float mLastMotionY;
Packit Service fa4841
	private float mLastMotionX;
Packit Service fa4841
	private boolean mIsLongpressEnabled;
Packit Service fa4841
	/**
Packit Service fa4841
	 * True if we are at a target API level of >= Froyo or the developer can
Packit Service fa4841
	 * explicitly set it. If true, input events with > 1 pointer will be ignored
Packit Service fa4841
	 * so we can work side by side with multitouch gesture detectors.
Packit Service fa4841
	 */
Packit Service fa4841
	private boolean mIgnoreMultitouch;
Packit Service fa4841
	/**
Packit Service fa4841
	 * Creates a GestureDetector with the supplied listener.
Packit Service fa4841
	 * You may only use this constructor from a UI thread (this is the usual situation).
Packit Service fa4841
	 *
Packit Service fa4841
	 * @param context  the application's context
Packit Service fa4841
	 * @param listener the listener invoked for all the callbacks, this must
Packit Service fa4841
	 *                 not be null.
Packit Service fa4841
	 * @throws NullPointerException if {@code listener} is null.
Packit Service fa4841
	 * @see android.os.Handler#Handler()
Packit Service fa4841
	 */
Packit Service fa4841
	public GestureDetector(Context context, OnGestureListener listener)
Packit Service fa4841
	{
Packit Service fa4841
		this(context, listener, null);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * Creates a GestureDetector with the supplied listener.
Packit Service fa4841
	 * You may only use this constructor from a UI thread (this is the usual situation).
Packit Service fa4841
	 *
Packit Service fa4841
	 * @param context  the application's context
Packit Service fa4841
	 * @param listener the listener invoked for all the callbacks, this must
Packit Service fa4841
	 *                 not be null.
Packit Service fa4841
	 * @param handler  the handler to use
Packit Service fa4841
	 * @throws NullPointerException if {@code listener} is null.
Packit Service fa4841
	 * @see android.os.Handler#Handler()
Packit Service fa4841
	 */
Packit Service fa4841
	public GestureDetector(Context context, OnGestureListener listener, Handler handler)
Packit Service fa4841
	{
Packit Service fa4841
		this(context, listener, handler,
Packit Service fa4841
		     context != null &&
Packit Service fa4841
		         context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * Creates a GestureDetector with the supplied listener.
Packit Service fa4841
	 * You may only use this constructor from a UI thread (this is the usual situation).
Packit Service fa4841
	 *
Packit Service fa4841
	 * @param context          the application's context
Packit Service fa4841
	 * @param listener         the listener invoked for all the callbacks, this must
Packit Service fa4841
	 *                         not be null.
Packit Service fa4841
	 * @param handler          the handler to use
Packit Service fa4841
	 * @param ignoreMultitouch whether events involving more than one pointer should
Packit Service fa4841
	 *                         be ignored.
Packit Service fa4841
	 * @throws NullPointerException if {@code listener} is null.
Packit Service fa4841
	 * @see android.os.Handler#Handler()
Packit Service fa4841
	 */
Packit Service fa4841
	public GestureDetector(Context context, OnGestureListener listener, Handler handler,
Packit Service fa4841
	                       boolean ignoreMultitouch)
Packit Service fa4841
	{
Packit Service fa4841
		if (handler != null)
Packit Service fa4841
		{
Packit Service fa4841
			mHandler = new GestureHandler(handler);
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			mHandler = new GestureHandler();
Packit Service fa4841
		}
Packit Service fa4841
		mListener = listener;
Packit Service fa4841
		if (listener instanceof OnDoubleTapListener)
Packit Service fa4841
		{
Packit Service fa4841
			setOnDoubleTapListener((OnDoubleTapListener)listener);
Packit Service fa4841
		}
Packit Service fa4841
		init(context, ignoreMultitouch);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	private void init(Context context, boolean ignoreMultitouch)
Packit Service fa4841
	{
Packit Service fa4841
		if (mListener == null)
Packit Service fa4841
		{
Packit Service fa4841
			throw new NullPointerException("OnGestureListener must not be null");
Packit Service fa4841
		}
Packit Service fa4841
		mIsLongpressEnabled = true;
Packit Service fa4841
		mIgnoreMultitouch = ignoreMultitouch;
Packit Service fa4841
Packit Service fa4841
		// Fallback to support pre-donuts releases
Packit Service fa4841
		int touchSlop, largeTouchSlop, doubleTapSlop;
Packit Service fa4841
		if (context == null)
Packit Service fa4841
		{
Packit Service fa4841
			// noinspection deprecation
Packit Service fa4841
			touchSlop = ViewConfiguration.getTouchSlop();
Packit Service fa4841
			largeTouchSlop = touchSlop + 2;
Packit Service fa4841
			doubleTapSlop = DOUBLE_TAP_SLOP;
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
Packit Service fa4841
			final float density = metrics.density;
Packit Service fa4841
			final ViewConfiguration configuration = ViewConfiguration.get(context);
Packit Service fa4841
			touchSlop = configuration.getScaledTouchSlop();
Packit Service fa4841
			largeTouchSlop = (int)(density * LARGE_TOUCH_SLOP + 0.5f);
Packit Service fa4841
			doubleTapSlop = configuration.getScaledDoubleTapSlop();
Packit Service fa4841
		}
Packit Service fa4841
		mTouchSlopSquare = touchSlop * touchSlop;
Packit Service fa4841
		mLargeTouchSlopSquare = largeTouchSlop * largeTouchSlop;
Packit Service fa4841
		mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * Sets the listener which will be called for double-tap and related
Packit Service fa4841
	 * gestures.
Packit Service fa4841
	 *
Packit Service fa4841
	 * @param onDoubleTapListener the listener invoked for all the callbacks, or
Packit Service fa4841
	 *                            null to stop listening for double-tap gestures.
Packit Service fa4841
	 */
Packit Service fa4841
	public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener)
Packit Service fa4841
	{
Packit Service fa4841
		mDoubleTapListener = onDoubleTapListener;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * Set whether longpress is enabled, if this is enabled when a user
Packit Service fa4841
	 * presses and holds down you get a longpress event and nothing further.
Packit Service fa4841
	 * If it's disabled the user can press and hold down and then later
Packit Service fa4841
	 * moved their finger and you will get scroll events. By default
Packit Service fa4841
	 * longpress is enabled.
Packit Service fa4841
	 *
Packit Service fa4841
	 * @param isLongpressEnabled whether longpress should be enabled.
Packit Service fa4841
	 */
Packit Service fa4841
	public void setIsLongpressEnabled(boolean isLongpressEnabled)
Packit Service fa4841
	{
Packit Service fa4841
		mIsLongpressEnabled = isLongpressEnabled;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * @return true if longpress is enabled, else false.
Packit Service fa4841
	 */
Packit Service fa4841
	public boolean isLongpressEnabled()
Packit Service fa4841
	{
Packit Service fa4841
		return mIsLongpressEnabled;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	public void setLongPressTimeout(int timeout)
Packit Service fa4841
	{
Packit Service fa4841
		mLongpressTimeout = timeout;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * Analyzes the given motion event and if applicable triggers the
Packit Service fa4841
	 * appropriate callbacks on the {@link OnGestureListener} supplied.
Packit Service fa4841
	 *
Packit Service fa4841
	 * @param ev The current motion event.
Packit Service fa4841
	 * @return true if the {@link OnGestureListener} consumed the event,
Packit Service fa4841
	 * else false.
Packit Service fa4841
	 */
Packit Service fa4841
	public boolean onTouchEvent(MotionEvent ev)
Packit Service fa4841
	{
Packit Service fa4841
		final int action = ev.getAction();
Packit Service fa4841
		final float y = ev.getY();
Packit Service fa4841
		final float x = ev.getX();
Packit Service fa4841
Packit Service fa4841
		boolean handled = false;
Packit Service fa4841
Packit Service fa4841
		switch (action & MotionEvent.ACTION_MASK)
Packit Service fa4841
		{
Packit Service fa4841
			case MotionEvent.ACTION_POINTER_DOWN:
Packit Service fa4841
				if (mIgnoreMultitouch)
Packit Service fa4841
				{
Packit Service fa4841
					// Multitouch event - abort.
Packit Service fa4841
					cancel();
Packit Service fa4841
				}
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case MotionEvent.ACTION_POINTER_UP:
Packit Service fa4841
				// Ending a multitouch gesture and going back to 1 finger
Packit Service fa4841
				if (mIgnoreMultitouch && ev.getPointerCount() == 2)
Packit Service fa4841
				{
Packit Service fa4841
					int index = (((action & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
Packit Service fa4841
					              MotionEvent.ACTION_POINTER_INDEX_SHIFT) == 0)
Packit Service fa4841
					                ? 1
Packit Service fa4841
					                : 0;
Packit Service fa4841
					mLastMotionX = ev.getX(index);
Packit Service fa4841
					mLastMotionY = ev.getY(index);
Packit Service fa4841
				}
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case MotionEvent.ACTION_DOWN:
Packit Service fa4841
				if (mDoubleTapListener != null)
Packit Service fa4841
				{
Packit Service fa4841
					boolean hadTapMessage = mHandler.hasMessages(TAP);
Packit Service fa4841
					if (hadTapMessage)
Packit Service fa4841
						mHandler.removeMessages(TAP);
Packit Service fa4841
					if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) &&
Packit Service fa4841
					    hadTapMessage &&
Packit Service fa4841
					    isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev))
Packit Service fa4841
					{
Packit Service fa4841
						// This is a second tap
Packit Service fa4841
						mIsDoubleTapping = true;
Packit Service fa4841
						// Give a callback with the first tap of the double-tap
Packit Service fa4841
						handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
Packit Service fa4841
						// Give a callback with down event of the double-tap
Packit Service fa4841
						handled |= mDoubleTapListener.onDoubleTapEvent(ev);
Packit Service fa4841
					}
Packit Service fa4841
					else
Packit Service fa4841
					{
Packit Service fa4841
						// This is a first tap
Packit Service fa4841
						mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
Packit Service fa4841
					}
Packit Service fa4841
				}
Packit Service fa4841
Packit Service fa4841
				mLastMotionX = x;
Packit Service fa4841
				mLastMotionY = y;
Packit Service fa4841
				if (mCurrentDownEvent != null)
Packit Service fa4841
				{
Packit Service fa4841
					mCurrentDownEvent.recycle();
Packit Service fa4841
				}
Packit Service fa4841
				mCurrentDownEvent = MotionEvent.obtain(ev);
Packit Service fa4841
				mAlwaysInTapRegion = true;
Packit Service fa4841
				mAlwaysInBiggerTapRegion = true;
Packit Service fa4841
				mStillDown = true;
Packit Service fa4841
				mInLongPress = false;
Packit Service fa4841
Packit Service fa4841
				if (mIsLongpressEnabled)
Packit Service fa4841
				{
Packit Service fa4841
					mHandler.removeMessages(LONG_PRESS);
Packit Service fa4841
					mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime() +
Packit Service fa4841
					                                                TAP_TIMEOUT +
Packit Service fa4841
					                                                mLongpressTimeout);
Packit Service fa4841
				}
Packit Service fa4841
				mHandler.sendEmptyMessageAtTime(SHOW_PRESS,
Packit Service fa4841
				                                mCurrentDownEvent.getDownTime() + TAP_TIMEOUT);
Packit Service fa4841
				handled |= mListener.onDown(ev);
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case MotionEvent.ACTION_MOVE:
Packit Service fa4841
				if (mIgnoreMultitouch && ev.getPointerCount() > 1)
Packit Service fa4841
				{
Packit Service fa4841
					break;
Packit Service fa4841
				}
Packit Service fa4841
				final float scrollX = mLastMotionX - x;
Packit Service fa4841
				final float scrollY = mLastMotionY - y;
Packit Service fa4841
				if (mIsDoubleTapping)
Packit Service fa4841
				{
Packit Service fa4841
					// Give the move events of the double-tap
Packit Service fa4841
					handled |= mDoubleTapListener.onDoubleTapEvent(ev);
Packit Service fa4841
				}
Packit Service fa4841
				else if (mAlwaysInTapRegion)
Packit Service fa4841
				{
Packit Service fa4841
					final int deltaX = (int)(x - mCurrentDownEvent.getX());
Packit Service fa4841
					final int deltaY = (int)(y - mCurrentDownEvent.getY());
Packit Service fa4841
					int distance = (deltaX * deltaX) + (deltaY * deltaY);
Packit Service fa4841
					if (distance > mTouchSlopSquare)
Packit Service fa4841
					{
Packit Service fa4841
						mLastMotionX = x;
Packit Service fa4841
						mLastMotionY = y;
Packit Service fa4841
						mAlwaysInTapRegion = false;
Packit Service fa4841
						mHandler.removeMessages(TAP);
Packit Service fa4841
						mHandler.removeMessages(SHOW_PRESS);
Packit Service fa4841
						mHandler.removeMessages(LONG_PRESS);
Packit Service fa4841
					}
Packit Service fa4841
					if (distance > mLargeTouchSlopSquare)
Packit Service fa4841
					{
Packit Service fa4841
						mAlwaysInBiggerTapRegion = false;
Packit Service fa4841
					}
Packit Service fa4841
					handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
Packit Service fa4841
				}
Packit Service fa4841
				else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1))
Packit Service fa4841
				{
Packit Service fa4841
					handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
Packit Service fa4841
					mLastMotionX = x;
Packit Service fa4841
					mLastMotionY = y;
Packit Service fa4841
				}
Packit Service fa4841
				break;
Packit Service fa4841
Packit Service fa4841
			case MotionEvent.ACTION_UP:
Packit Service fa4841
				mStillDown = false;
Packit Service fa4841
				MotionEvent currentUpEvent = MotionEvent.obtain(ev);
Packit Service fa4841
				if (mIsDoubleTapping)
Packit Service fa4841
				{
Packit Service fa4841
					// Finally, give the up event of the double-tap
Packit Service fa4841
					handled |= mDoubleTapListener.onDoubleTapEvent(ev);
Packit Service fa4841
				}
Packit Service fa4841
				else if (mInLongPress)
Packit Service fa4841
				{
Packit Service fa4841
					mHandler.removeMessages(TAP);
Packit Service fa4841
					mListener.onLongPressUp(ev);
Packit Service fa4841
					mInLongPress = false;
Packit Service fa4841
				}
Packit Service fa4841
				else if (mAlwaysInTapRegion)
Packit Service fa4841
				{
Packit Service fa4841
					handled = mListener.onSingleTapUp(mCurrentDownEvent);
Packit Service fa4841
				}
Packit Service fa4841
				else
Packit Service fa4841
				{
Packit Service fa4841
					// A fling must travel the minimum tap distance
Packit Service fa4841
				}
Packit Service fa4841
				if (mPreviousUpEvent != null)
Packit Service fa4841
				{
Packit Service fa4841
					mPreviousUpEvent.recycle();
Packit Service fa4841
				}
Packit Service fa4841
				// Hold the event we obtained above - listeners may have changed the original.
Packit Service fa4841
				mPreviousUpEvent = currentUpEvent;
Packit Service fa4841
				mIsDoubleTapping = false;
Packit Service fa4841
				mHandler.removeMessages(SHOW_PRESS);
Packit Service fa4841
				mHandler.removeMessages(LONG_PRESS);
Packit Service fa4841
				handled |= mListener.onUp(ev);
Packit Service fa4841
				break;
Packit Service fa4841
			case MotionEvent.ACTION_CANCEL:
Packit Service fa4841
				cancel();
Packit Service fa4841
				break;
Packit Service fa4841
		}
Packit Service fa4841
		return handled;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	private void cancel()
Packit Service fa4841
	{
Packit Service fa4841
		mHandler.removeMessages(SHOW_PRESS);
Packit Service fa4841
		mHandler.removeMessages(LONG_PRESS);
Packit Service fa4841
		mHandler.removeMessages(TAP);
Packit Service fa4841
		mAlwaysInTapRegion = false; // ensures that we won't receive an OnSingleTap notification
Packit Service fa4841
		                            // when a 2-Finger tap is performed
Packit Service fa4841
		mIsDoubleTapping = false;
Packit Service fa4841
		mStillDown = false;
Packit Service fa4841
		if (mInLongPress)
Packit Service fa4841
		{
Packit Service fa4841
			mInLongPress = false;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
Packit Service fa4841
	                                      MotionEvent secondDown)
Packit Service fa4841
	{
Packit Service fa4841
		if (!mAlwaysInBiggerTapRegion)
Packit Service fa4841
		{
Packit Service fa4841
			return false;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIMEOUT)
Packit Service fa4841
		{
Packit Service fa4841
			return false;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		int deltaX = (int)firstDown.getX() - (int)secondDown.getX();
Packit Service fa4841
		int deltaY = (int)firstDown.getY() - (int)secondDown.getY();
Packit Service fa4841
		return (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	private void dispatchLongPress()
Packit Service fa4841
	{
Packit Service fa4841
		mHandler.removeMessages(TAP);
Packit Service fa4841
		mInLongPress = true;
Packit Service fa4841
		mListener.onLongPress(mCurrentDownEvent);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * The listener that is used to notify when gestures occur.
Packit Service fa4841
	 * If you want to listen for all the different gestures then implement
Packit Service fa4841
	 * this interface. If you only want to listen for a subset it might
Packit Service fa4841
	 * be easier to extend {@link SimpleOnGestureListener}.
Packit Service fa4841
	 */
Packit Service fa4841
	public interface OnGestureListener {
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * Notified when a tap occurs with the down {@link MotionEvent}
Packit Service fa4841
		 * that triggered it. This will be triggered immediately for
Packit Service fa4841
		 * every down event. All other events should be preceded by this.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e The down motion event.
Packit Service fa4841
		 */
Packit Service fa4841
		boolean onDown(MotionEvent e);
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * Notified when a tap finishes with the up {@link MotionEvent}
Packit Service fa4841
		 * that triggered it. This will be triggered immediately for
Packit Service fa4841
		 * every up event. All other events should be preceded by this.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e The up motion event.
Packit Service fa4841
		 */
Packit Service fa4841
		boolean onUp(MotionEvent e);
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * The user has performed a down {@link MotionEvent} and not performed
Packit Service fa4841
		 * a move or up yet. This event is commonly used to provide visual
Packit Service fa4841
		 * feedback to the user to let them know that their action has been
Packit Service fa4841
		 * recognized i.e. highlight an element.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e The down motion event
Packit Service fa4841
		 */
Packit Service fa4841
		void onShowPress(MotionEvent e);
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * Notified when a tap occurs with the up {@link MotionEvent}
Packit Service fa4841
		 * that triggered it.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e The up motion event that completed the first tap
Packit Service fa4841
		 * @return true if the event is consumed, else false
Packit Service fa4841
		 */
Packit Service fa4841
		boolean onSingleTapUp(MotionEvent e);
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the
Packit Service fa4841
		 * current move {@link MotionEvent}. The distance in x and y is also supplied for
Packit Service fa4841
		 * convenience.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e1        The first down motion event that started the scrolling.
Packit Service fa4841
		 * @param e2        The move motion event that triggered the current onScroll.
Packit Service fa4841
		 * @param distanceX The distance along the X axis that has been scrolled since the last
Packit Service fa4841
		 *                  call to onScroll. This is NOT the distance between {@code e1}
Packit Service fa4841
		 *                  and {@code e2}.
Packit Service fa4841
		 * @param distanceY The distance along the Y axis that has been scrolled since the last
Packit Service fa4841
		 *                  call to onScroll. This is NOT the distance between {@code e1}
Packit Service fa4841
		 *                  and {@code e2}.
Packit Service fa4841
		 * @return true if the event is consumed, else false
Packit Service fa4841
		 */
Packit Service fa4841
		boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * Notified when a long press occurs with the initial on down {@link MotionEvent}
Packit Service fa4841
		 * that trigged it.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e The initial on down motion event that started the longpress.
Packit Service fa4841
		 */
Packit Service fa4841
		void onLongPress(MotionEvent e);
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * Notified when a long press ends with the final {@link MotionEvent}.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e The up motion event that ended the longpress.
Packit Service fa4841
		 */
Packit Service fa4841
		void onLongPressUp(MotionEvent e);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * The listener that is used to notify when a double-tap or a confirmed
Packit Service fa4841
	 * single-tap occur.
Packit Service fa4841
	 */
Packit Service fa4841
	public interface OnDoubleTapListener {
Packit Service fa4841
		/**
Packit Service fa4841
		 * Notified when a single-tap occurs.
Packit Service fa4841
		 * 

Packit Service fa4841
		 * Unlike {@link OnGestureListener#onSingleTapUp(MotionEvent)}, this
Packit Service fa4841
		 * will only be called after the detector is confident that the user's
Packit Service fa4841
		 * first tap is not followed by a second tap leading to a double-tap
Packit Service fa4841
		 * gesture.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e The down motion event of the single-tap.
Packit Service fa4841
		 * @return true if the event is consumed, else false
Packit Service fa4841
		 */
Packit Service fa4841
		boolean onSingleTapConfirmed(MotionEvent e);
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * Notified when a double-tap occurs.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e The down motion event of the first tap of the double-tap.
Packit Service fa4841
		 * @return true if the event is consumed, else false
Packit Service fa4841
		 */
Packit Service fa4841
		boolean onDoubleTap(MotionEvent e);
Packit Service fa4841
Packit Service fa4841
		/**
Packit Service fa4841
		 * Notified when an event within a double-tap gesture occurs, including
Packit Service fa4841
		 * the down, move, and up events.
Packit Service fa4841
		 *
Packit Service fa4841
		 * @param e The motion event that occurred during the double-tap gesture.
Packit Service fa4841
		 * @return true if the event is consumed, else false
Packit Service fa4841
		 */
Packit Service fa4841
		boolean onDoubleTapEvent(MotionEvent e);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * A convenience class to extend when you only want to listen for a subset
Packit Service fa4841
	 * of all the gestures. This implements all methods in the
Packit Service fa4841
	 * {@link OnGestureListener} and {@link OnDoubleTapListener} but does
Packit Service fa4841
	 * nothing and return {@code false} for all applicable methods.
Packit Service fa4841
	 */
Packit Service fa4841
	public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener
Packit Service fa4841
	{
Packit Service fa4841
		public boolean onSingleTapUp(MotionEvent e)
Packit Service fa4841
		{
Packit Service fa4841
			return false;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		public void onLongPress(MotionEvent e)
Packit Service fa4841
		{
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		public void onLongPressUp(MotionEvent e)
Packit Service fa4841
		{
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
Packit Service fa4841
		{
Packit Service fa4841
			return false;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		public void onShowPress(MotionEvent e)
Packit Service fa4841
		{
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		public boolean onDown(MotionEvent e)
Packit Service fa4841
		{
Packit Service fa4841
			return false;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		public boolean onUp(MotionEvent e)
Packit Service fa4841
		{
Packit Service fa4841
			return false;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		public boolean onDoubleTap(MotionEvent e)
Packit Service fa4841
		{
Packit Service fa4841
			return false;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		public boolean onDoubleTapEvent(MotionEvent e)
Packit Service fa4841
		{
Packit Service fa4841
			return false;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		public boolean onSingleTapConfirmed(MotionEvent e)
Packit Service fa4841
		{
Packit Service fa4841
			return false;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	private class GestureHandler extends Handler
Packit Service fa4841
	{
Packit Service fa4841
		GestureHandler()
Packit Service fa4841
		{
Packit Service fa4841
			super();
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		GestureHandler(Handler handler)
Packit Service fa4841
		{
Packit Service fa4841
			super(handler.getLooper());
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		@Override public void handleMessage(Message msg)
Packit Service fa4841
		{
Packit Service fa4841
			switch (msg.what)
Packit Service fa4841
			{
Packit Service fa4841
				case SHOW_PRESS:
Packit Service fa4841
					mListener.onShowPress(mCurrentDownEvent);
Packit Service fa4841
					break;
Packit Service fa4841
Packit Service fa4841
				case LONG_PRESS:
Packit Service fa4841
					dispatchLongPress();
Packit Service fa4841
					break;
Packit Service fa4841
Packit Service fa4841
				case TAP:
Packit Service fa4841
					// If the user's finger is still down, do not count it as a tap
Packit Service fa4841
					if (mDoubleTapListener != null && !mStillDown)
Packit Service fa4841
					{
Packit Service fa4841
						mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
Packit Service fa4841
					}
Packit Service fa4841
					break;
Packit Service fa4841
Packit Service fa4841
				default:
Packit Service fa4841
					throw new RuntimeException("Unknown message " + msg); // never
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
}