19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.view; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powellimport android.content.Context; 20216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powellimport android.os.Build; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Detects various gestures and events using the supplied {@link MotionEvent}s. 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The {@link OnGestureListener} callback will notify users when a particular 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * motion event has occurred. This class should only be used with {@link MotionEvent}s 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * reported via touch (don't use for trackball events). 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To use this class: 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul> 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>Create an instance of the {@code GestureDetector} for your {@link View} 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be executed when the events occur. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GestureDetector { 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The listener that is used to notify when gestures occur. 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If you want to listen for all the different gestures then implement 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this interface. If you only want to listen for a subset it might 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be easier to extend {@link SimpleOnGestureListener}. 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnGestureListener { 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notified when a tap occurs with the down {@link MotionEvent} 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that triggered it. This will be triggered immediately for 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * every down event. All other events should be preceded by this. 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e The down motion event. 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onDown(MotionEvent e); 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The user has performed a down {@link MotionEvent} and not performed 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a move or up yet. This event is commonly used to provide visual 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * feedback to the user to let them know that their action has been 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * recognized i.e. highlight an element. 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e The down motion event 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onShowPress(MotionEvent e); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notified when a tap occurs with the up {@link MotionEvent} 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that triggered it. 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e The up motion event that completed the first tap 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the event is consumed, else false 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onSingleTapUp(MotionEvent e); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * current move {@link MotionEvent}. The distance in x and y is also supplied for 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * convenience. 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e1 The first down motion event that started the scrolling. 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e2 The move motion event that triggered the current onScroll. 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param distanceX The distance along the X axis that has been scrolled since the last 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * call to onScroll. This is NOT the distance between {@code e1} 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and {@code e2}. 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param distanceY The distance along the Y axis that has been scrolled since the last 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * call to onScroll. This is NOT the distance between {@code e1} 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and {@code e2}. 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the event is consumed, else false 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notified when a long press occurs with the initial on down {@link MotionEvent} 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that trigged it. 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e The initial on down motion event that started the longpress. 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onLongPress(MotionEvent e); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notified of a fling event when it occurs with the initial on down {@link MotionEvent} 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and the matching up {@link MotionEvent}. The calculated velocity is supplied along 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the x and y axis in pixels per second. 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e1 The first down motion event that started the fling. 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e2 The move motion event that triggered the current onFling. 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param velocityX The velocity of this fling measured in pixels per second 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * along the x axis. 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param velocityY The velocity of this fling measured in pixels per second 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * along the y axis. 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the event is consumed, else false 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The listener that is used to notify when a double-tap or a confirmed 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * single-tap occur. 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnDoubleTapListener { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notified when a single-tap occurs. 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unlike {@link OnGestureListener#onSingleTapUp(MotionEvent)}, this 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will only be called after the detector is confident that the user's 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * first tap is not followed by a second tap leading to a double-tap 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * gesture. 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e The down motion event of the single-tap. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the event is consumed, else false 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onSingleTapConfirmed(MotionEvent e); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notified when a double-tap occurs. 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e The down motion event of the first tap of the double-tap. 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the event is consumed, else false 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onDoubleTap(MotionEvent e); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notified when an event within a double-tap gesture occurs, including 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the down, move, and up events. 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param e The motion event that occurred during the double-tap gesture. 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the event is consumed, else false 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onDoubleTapEvent(MotionEvent e); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A convenience class to extend when you only want to listen for a subset 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of all the gestures. This implements all methods in the 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link OnGestureListener} and {@link OnDoubleTapListener} but does 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * nothing and return {@code false} for all applicable methods. 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener { 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onSingleTapUp(MotionEvent e) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onLongPress(MotionEvent e) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onScroll(MotionEvent e1, MotionEvent e2, 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float distanceX, float distanceY) { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float velocityY) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onShowPress(MotionEvent e) { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onDown(MotionEvent e) { 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onDoubleTap(MotionEvent e) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onDoubleTapEvent(MotionEvent e) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onSingleTapConfirmed(MotionEvent e) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mTouchSlopSquare; 197006fa48bce7759013d9025376cd5167236c434a7Gilles Debunne private int mDoubleTapTouchSlopSquare; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDoubleTapSlopSquare; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMinimumFlingVelocity; 2004296fc4d326447875c26a925f12b3935632f13bbRomain Guy private int mMaximumFlingVelocity; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout(); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout(); 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // constants for Message.what used by GestureHandler below 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SHOW_PRESS = 1; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LONG_PRESS = 2; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int TAP = 3; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Handler mHandler; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final OnGestureListener mListener; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnDoubleTapListener mDoubleTapListener; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mStillDown; 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mInLongPress; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mAlwaysInTapRegion; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mAlwaysInBiggerTapRegion; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MotionEvent mCurrentDownEvent; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MotionEvent mPreviousUpEvent; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * True when the user is still touching for the second tap (down, move, and 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * up events). Can only be true if there is a double tap listener attached. 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsDoubleTapping; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2298be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell private float mLastFocusX; 2308be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell private float mLastFocusY; 2318be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell private float mDownFocusX; 2328be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell private float mDownFocusY; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mIsLongpressEnabled; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Determines speed during touch scrolling 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private VelocityTracker mVelocityTracker; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 24221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Consistency verifier for debugging purposes. 24321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 24421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private final InputEventConsistencyVerifier mInputEventConsistencyVerifier = 24521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown InputEventConsistencyVerifier.isInstrumentationEnabled() ? 24621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown new InputEventConsistencyVerifier(this, 0) : null; 24721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class GestureHandler extends Handler { 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GestureHandler() { 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GestureHandler(Handler handler) { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(handler.getLooper()); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SHOW_PRESS: 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListener.onShowPress(mCurrentDownEvent); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LONG_PRESS: 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dispatchLongPress(); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case TAP: 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the user's finger is still down, do not count it as a tap 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDoubleTapListener != null && !mStillDown) { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("Unknown message " + msg); //never 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a GestureDetector with the supplied listener. 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This variant of the constructor should be used from a non-UI thread 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (as it allows specifying the Handler). 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the listener invoked for all the callbacks, this must 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not be null. 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param handler the handler to use 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws NullPointerException if either {@code listener} or 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@code handler} is null. 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @deprecated Use {@link #GestureDetector(android.content.Context, 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android.view.GestureDetector.OnGestureListener, android.os.Handler)} instead. 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Deprecated 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GestureDetector(OnGestureListener listener, Handler handler) { 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(null, listener, handler); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a GestureDetector with the supplied listener. 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may only use this constructor from a UI thread (this is the usual situation). 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.os.Handler#Handler() 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the listener invoked for all the callbacks, this must 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not be null. 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws NullPointerException if {@code listener} is null. 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @deprecated Use {@link #GestureDetector(android.content.Context, 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android.view.GestureDetector.OnGestureListener)} instead. 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Deprecated 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GestureDetector(OnGestureListener listener) { 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(null, listener, null); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a GestureDetector with the supplied listener. 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may only use this constructor from a UI thread (this is the usual situation). 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.os.Handler#Handler() 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context the application's context 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the listener invoked for all the callbacks, this must 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not be null. 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws NullPointerException if {@code listener} is null. 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GestureDetector(Context context, OnGestureListener listener) { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, listener, null); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a GestureDetector with the supplied listener. 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may only use this constructor from a UI thread (this is the usual situation). 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.os.Handler#Handler() 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context the application's context 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the listener invoked for all the callbacks, this must 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not be null. 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param handler the handler to use 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws NullPointerException if {@code listener} is null. 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GestureDetector(Context context, OnGestureListener listener, Handler handler) { 3478be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell if (handler != null) { 3488be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mHandler = new GestureHandler(handler); 3498be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell } else { 3508be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mHandler = new GestureHandler(); 3518be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell } 3528be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mListener = listener; 3538be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell if (listener instanceof OnDoubleTapListener) { 3548be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell setOnDoubleTapListener((OnDoubleTapListener) listener); 3558be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell } 3568be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell init(context); 357216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell } 358216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell 359216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell /** 360216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * Creates a GestureDetector with the supplied listener. 361216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * You may only use this constructor from a UI thread (this is the usual situation). 362216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * @see android.os.Handler#Handler() 363216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * 364216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * @param context the application's context 365216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * @param listener the listener invoked for all the callbacks, this must 366216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * not be null. 367216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * @param handler the handler to use 368216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * 369216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell * @throws NullPointerException if {@code listener} is null. 370216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell */ 371216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell public GestureDetector(Context context, OnGestureListener listener, Handler handler, 3728be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell boolean unused) { 3738be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell this(context, listener, handler); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3768be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell private void init(Context context) { 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mListener == null) { 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new NullPointerException("OnGestureListener must not be null"); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsLongpressEnabled = true; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fallback to support pre-donuts releases 383006fa48bce7759013d9025376cd5167236c434a7Gilles Debunne int touchSlop, doubleTapSlop, doubleTapTouchSlop; 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (context == null) { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection deprecation 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project touchSlop = ViewConfiguration.getTouchSlop(); 387006fa48bce7759013d9025376cd5167236c434a7Gilles Debunne doubleTapTouchSlop = touchSlop; // Hack rather than adding a hiden method for this 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project doubleTapSlop = ViewConfiguration.getDoubleTapSlop(); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection deprecation 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity(); 3914296fc4d326447875c26a925f12b3935632f13bbRomain Guy mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity(); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ViewConfiguration configuration = ViewConfiguration.get(context); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project touchSlop = configuration.getScaledTouchSlop(); 395006fa48bce7759013d9025376cd5167236c434a7Gilles Debunne doubleTapTouchSlop = configuration.getScaledDoubleTapTouchSlop(); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project doubleTapSlop = configuration.getScaledDoubleTapSlop(); 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity(); 3984296fc4d326447875c26a925f12b3935632f13bbRomain Guy mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity(); 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTouchSlopSquare = touchSlop * touchSlop; 401006fa48bce7759013d9025376cd5167236c434a7Gilles Debunne mDoubleTapTouchSlopSquare = doubleTapTouchSlop * doubleTapTouchSlop; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the listener which will be called for double-tap and related 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * gestures. 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param onDoubleTapListener the listener invoked for all the callbacks, or 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * null to stop listening for double-tap gestures. 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener) { 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDoubleTapListener = onDoubleTapListener; 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set whether longpress is enabled, if this is enabled when a user 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * presses and holds down you get a longpress event and nothing further. 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If it's disabled the user can press and hold down and then later 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * moved their finger and you will get scroll events. By default 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * longpress is enabled. 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param isLongpressEnabled whether longpress should be enabled. 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setIsLongpressEnabled(boolean isLongpressEnabled) { 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsLongpressEnabled = isLongpressEnabled; 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if longpress is enabled, else false. 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isLongpressEnabled() { 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mIsLongpressEnabled; 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Analyzes the given motion event and if applicable triggers the 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * appropriate callbacks on the {@link OnGestureListener} supplied. 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param ev The current motion event. 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the {@link OnGestureListener} consumed the event, 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * else false. 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onTouchEvent(MotionEvent ev) { 44521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mInputEventConsistencyVerifier != null) { 44621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mInputEventConsistencyVerifier.onTouchEvent(ev, 0); 44721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 44821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int action = ev.getAction(); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mVelocityTracker == null) { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVelocityTracker = VelocityTracker.obtain(); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVelocityTracker.addMovement(ev); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 456c104d168789450d655f7efbab209dbf4d125bac4Adam Powell final boolean pointerUp = 457c104d168789450d655f7efbab209dbf4d125bac4Adam Powell (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP; 4588be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final int skipIndex = pointerUp ? ev.getActionIndex() : -1; 4598be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell 4608be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell // Determine focal point 4618be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell float sumX = 0, sumY = 0; 4628be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final int count = ev.getPointerCount(); 4638be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell for (int i = 0; i < count; i++) { 4648be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell if (skipIndex == i) continue; 4658be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell sumX += ev.getX(i); 4668be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell sumY += ev.getY(i); 4678be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell } 4688be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final int div = pointerUp ? count - 1 : count; 4698be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final float focusX = sumX / div; 4708be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final float focusY = sumY / div; 4718be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean handled = false; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 474216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell switch (action & MotionEvent.ACTION_MASK) { 475216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell case MotionEvent.ACTION_POINTER_DOWN: 4768be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mDownFocusX = mLastFocusX = focusX; 4778be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mDownFocusY = mLastFocusY = focusY; 4788be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell // Cancel long press and taps 4798be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell cancelTaps(); 480216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell break; 481216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell 482216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell case MotionEvent.ACTION_POINTER_UP: 4838be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mDownFocusX = mLastFocusX = focusX; 4848be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mDownFocusY = mLastFocusY = focusY; 485216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell break; 486216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_DOWN: 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDoubleTapListener != null) { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean hadTapMessage = mHandler.hasMessages(TAP); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hadTapMessage) mHandler.removeMessages(TAP); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage && 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is a second tap 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIsDoubleTapping = true; 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Give a callback with the first tap of the double-tap 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Give a callback with down event of the double-tap 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled |= mDoubleTapListener.onDoubleTapEvent(ev); 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is a first tap 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5058be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mDownFocusX = mLastFocusX = focusX; 5068be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mDownFocusY = mLastFocusY = focusY; 50745f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell if (mCurrentDownEvent != null) { 50845f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell mCurrentDownEvent.recycle(); 50945f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell } 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCurrentDownEvent = MotionEvent.obtain(ev); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAlwaysInTapRegion = true; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAlwaysInBiggerTapRegion = true; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStillDown = true; 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInLongPress = false; 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsLongpressEnabled) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(LONG_PRESS); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime() 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + TAP_TIMEOUT + LONGPRESS_TIMEOUT); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled |= mListener.onDown(ev); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_MOVE: 5268be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell if (mInLongPress) { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5298be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final float scrollX = mLastFocusX - focusX; 5308be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final float scrollY = mLastFocusY - focusY; 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsDoubleTapping) { 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Give the move events of the double-tap 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled |= mDoubleTapListener.onDoubleTapEvent(ev); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mAlwaysInTapRegion) { 5358be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final int deltaX = (int) (focusX - mDownFocusX); 5368be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final int deltaY = (int) (focusY - mDownFocusY); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int distance = (deltaX * deltaX) + (deltaY * deltaY); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (distance > mTouchSlopSquare) { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); 5408be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mLastFocusX = focusX; 5418be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mLastFocusY = focusY; 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAlwaysInTapRegion = false; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(TAP); 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(SHOW_PRESS); 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(LONG_PRESS); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 547006fa48bce7759013d9025376cd5167236c434a7Gilles Debunne if (distance > mDoubleTapTouchSlopSquare) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAlwaysInBiggerTapRegion = false; 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY); 5528be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mLastFocusX = focusX; 5538be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mLastFocusY = focusY; 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_UP: 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStillDown = false; 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MotionEvent currentUpEvent = MotionEvent.obtain(ev); 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mIsDoubleTapping) { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Finally, give the up event of the double-tap 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled |= mDoubleTapListener.onDoubleTapEvent(ev); 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mInLongPress) { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(TAP); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInLongPress = false; 566f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project } else if (mAlwaysInTapRegion) { 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = mListener.onSingleTapUp(ev); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // A fling must travel the minimum tap distance 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final VelocityTracker velocityTracker = mVelocityTracker; 5728be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final int pointerId = ev.getPointerId(0); 5734296fc4d326447875c26a925f12b3935632f13bbRomain Guy velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); 5748be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final float velocityY = velocityTracker.getYVelocity(pointerId); 5758be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell final float velocityX = velocityTracker.getXVelocity(pointerId); 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((Math.abs(velocityY) > mMinimumFlingVelocity) 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || (Math.abs(velocityX) > mMinimumFlingVelocity)){ 57945f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY); 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 58245f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell if (mPreviousUpEvent != null) { 58345f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell mPreviousUpEvent.recycle(); 58445f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell } 58545f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell // Hold the event we obtained above - listeners may have changed the original. 58645f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell mPreviousUpEvent = currentUpEvent; 5877a83b93e12e4a215b90bfa32a753a5a53525d011Dianne Hackborn if (mVelocityTracker != null) { 5887a83b93e12e4a215b90bfa32a753a5a53525d011Dianne Hackborn // This may have been cleared when we called out to the 5897a83b93e12e4a215b90bfa32a753a5a53525d011Dianne Hackborn // application above. 5907a83b93e12e4a215b90bfa32a753a5a53525d011Dianne Hackborn mVelocityTracker.recycle(); 5917a83b93e12e4a215b90bfa32a753a5a53525d011Dianne Hackborn mVelocityTracker = null; 5927a83b93e12e4a215b90bfa32a753a5a53525d011Dianne Hackborn } 593b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project mIsDoubleTapping = false; 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(SHOW_PRESS); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(LONG_PRESS); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 597bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_CANCEL: 599216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell cancel(); 600bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown break; 601bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 602bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown 603bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (!handled && mInputEventConsistencyVerifier != null) { 604bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mInputEventConsistencyVerifier.onUnhandledEvent(ev, 0); 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return handled; 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell private void cancel() { 610216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell mHandler.removeMessages(SHOW_PRESS); 611216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell mHandler.removeMessages(LONG_PRESS); 612216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell mHandler.removeMessages(TAP); 613216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell mVelocityTracker.recycle(); 614216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell mVelocityTracker = null; 615216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell mIsDoubleTapping = false; 616216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell mStillDown = false; 61717921eefe3d2219ee2348face5d650d33db64b06Adam Powell mAlwaysInTapRegion = false; 61817921eefe3d2219ee2348face5d650d33db64b06Adam Powell mAlwaysInBiggerTapRegion = false; 619216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell if (mInLongPress) { 620216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell mInLongPress = false; 621216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell } 622216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell } 623216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell 6248be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell private void cancelTaps() { 6258be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mHandler.removeMessages(SHOW_PRESS); 6268be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mHandler.removeMessages(LONG_PRESS); 6278be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mHandler.removeMessages(TAP); 6288be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mIsDoubleTapping = false; 6298be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mAlwaysInTapRegion = false; 6308be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mAlwaysInBiggerTapRegion = false; 6318be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell if (mInLongPress) { 6328be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell mInLongPress = false; 6338be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell } 6348be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell } 6358be03ace9500e03e6aa482713cdd07caf5ca6421Adam Powell 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp, 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MotionEvent secondDown) { 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAlwaysInBiggerTapRegion) { 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIMEOUT) { 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int deltaX = (int) firstDown.getX() - (int) secondDown.getX(); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int deltaY = (int) firstDown.getY() - (int) secondDown.getY(); 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare); 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void dispatchLongPress() { 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(TAP); 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInLongPress = true; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListener.onLongPress(mCurrentDownEvent); 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 657