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