GestureDetector.java revision 45f2ca7f7d9fac55aa228e022f46ecbac8712a15
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    // TODO: ViewConfiguration
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mBiggerTouchSlopSquare = 20 * 20;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTouchSlopSquare;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mDoubleTapSlopSquare;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mMinimumFlingVelocity;
2024296fc4d326447875c26a925f12b3935632f13bbRomain Guy    private int mMaximumFlingVelocity;
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // constants for Message.what used by GestureHandler below
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int SHOW_PRESS = 1;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LONG_PRESS = 2;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int TAP = 3;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Handler mHandler;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final OnGestureListener mListener;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnDoubleTapListener mDoubleTapListener;
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStillDown;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mInLongPress;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAlwaysInTapRegion;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAlwaysInBiggerTapRegion;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MotionEvent mCurrentDownEvent;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MotionEvent mPreviousUpEvent;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * True when the user is still touching for the second tap (down, move, and
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * up events). Can only be true if there is a double tap listener attached.
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsDoubleTapping;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mLastMotionY;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mLastMotionX;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsLongpressEnabled;
235216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell
236216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell    /**
237216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * True if we are at a target API level of >= Froyo or the developer can
238216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * explicitly set it. If true, input events with > 1 pointer will be ignored
239216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * so we can work side by side with multitouch gesture detectors.
240216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     */
241216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell    private boolean mIgnoreMultitouch;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Determines speed during touch scrolling
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private VelocityTracker mVelocityTracker;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
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) {
347216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        this(context, listener, handler, context != null &&
348216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO);
349216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell    }
350216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell
351216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell    /**
352216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * Creates a GestureDetector with the supplied listener.
353216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * You may only use this constructor from a UI thread (this is the usual situation).
354216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * @see android.os.Handler#Handler()
355216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     *
356216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * @param context the application's context
357216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * @param listener the listener invoked for all the callbacks, this must
358216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * not be null.
359216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * @param handler the handler to use
360216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * @param ignoreMultitouch whether events involving more than one pointer should
361216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * be ignored.
362216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     *
363216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     * @throws NullPointerException if {@code listener} is null.
364216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell     */
365216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell    public GestureDetector(Context context, OnGestureListener listener, Handler handler,
366216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            boolean ignoreMultitouch) {
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (handler != null) {
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler = new GestureHandler(handler);
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler = new GestureHandler();
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mListener = listener;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (listener instanceof OnDoubleTapListener) {
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setOnDoubleTapListener((OnDoubleTapListener) listener);
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
376216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        init(context, ignoreMultitouch);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell    private void init(Context context, boolean ignoreMultitouch) {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mListener == null) {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new NullPointerException("OnGestureListener must not be null");
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsLongpressEnabled = true;
384216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        mIgnoreMultitouch = ignoreMultitouch;
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Fallback to support pre-donuts releases
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int touchSlop, doubleTapSlop;
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (context == null) {
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //noinspection deprecation
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            touchSlop = ViewConfiguration.getTouchSlop();
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doubleTapSlop = ViewConfiguration.getDoubleTapSlop();
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //noinspection deprecation
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity();
3944296fc4d326447875c26a925f12b3935632f13bbRomain Guy            mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity();
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final ViewConfiguration configuration = ViewConfiguration.get(context);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            touchSlop = configuration.getScaledTouchSlop();
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            doubleTapSlop = configuration.getScaledDoubleTapSlop();
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity();
4004296fc4d326447875c26a925f12b3935632f13bbRomain Guy            mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity();
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTouchSlopSquare = touchSlop * touchSlop;
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop;
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the listener which will be called for double-tap and related
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * gestures.
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param onDoubleTapListener the listener invoked for all the callbacks, or
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        null to stop listening for double-tap gestures.
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener) {
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDoubleTapListener = onDoubleTapListener;
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set whether longpress is enabled, if this is enabled when a user
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * presses and holds down you get a longpress event and nothing further.
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If it's disabled the user can press and hold down and then later
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * moved their finger and you will get scroll events. By default
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * longpress is enabled.
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param isLongpressEnabled whether longpress should be enabled.
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setIsLongpressEnabled(boolean isLongpressEnabled) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsLongpressEnabled = isLongpressEnabled;
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if longpress is enabled, else false.
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isLongpressEnabled() {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mIsLongpressEnabled;
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Analyzes the given motion event and if applicable triggers the
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * appropriate callbacks on the {@link OnGestureListener} supplied.
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param ev The current motion event.
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the {@link OnGestureListener} consumed the event,
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *              else false.
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int action = ev.getAction();
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float y = ev.getY();
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float x = ev.getX();
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mVelocityTracker == null) {
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVelocityTracker = VelocityTracker.obtain();
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVelocityTracker.addMovement(ev);
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean handled = false;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
457216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        switch (action & MotionEvent.ACTION_MASK) {
458216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        case MotionEvent.ACTION_POINTER_DOWN:
459216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            if (mIgnoreMultitouch) {
460216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell                // Multitouch event - abort.
461216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell                cancel();
462216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            }
463216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            break;
464216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell
465216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        case MotionEvent.ACTION_POINTER_UP:
466216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            // Ending a multitouch gesture and going back to 1 finger
467216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            if (mIgnoreMultitouch && ev.getPointerCount() == 2) {
468b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn                int index = (((action & MotionEvent.ACTION_POINTER_INDEX_MASK)
469b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT) == 0) ? 1 : 0;
470b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn                mLastMotionX = ev.getX(index);
471b125dc5599468a09d82751cd76152071ae485afbDianne Hackborn                mLastMotionY = ev.getY(index);
472216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell                mVelocityTracker.recycle();
473216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell                mVelocityTracker = VelocityTracker.obtain();
474216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            }
475216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            break;
476216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case MotionEvent.ACTION_DOWN:
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDoubleTapListener != null) {
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean hadTapMessage = mHandler.hasMessages(TAP);
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (hadTapMessage) mHandler.removeMessages(TAP);
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage &&
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) {
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // This is a second tap
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mIsDoubleTapping = true;
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Give a callback with the first tap of the double-tap
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Give a callback with down event of the double-tap
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    handled |= mDoubleTapListener.onDoubleTapEvent(ev);
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // This is a first tap
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastMotionX = x;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastMotionY = y;
49745f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell            if (mCurrentDownEvent != null) {
49845f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell                mCurrentDownEvent.recycle();
49945f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell            }
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurrentDownEvent = MotionEvent.obtain(ev);
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAlwaysInTapRegion = true;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAlwaysInBiggerTapRegion = true;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStillDown = true;
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInLongPress = false;
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsLongpressEnabled) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHandler.removeMessages(LONG_PRESS);
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime()
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + TAP_TIMEOUT + LONGPRESS_TIMEOUT);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT);
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handled |= mListener.onDown(ev);
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case MotionEvent.ACTION_MOVE:
516216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            if (mInLongPress || (mIgnoreMultitouch && ev.getPointerCount() > 1)) {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float scrollX = mLastMotionX - x;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final float scrollY = mLastMotionY - y;
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsDoubleTapping) {
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Give the move events of the double-tap
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handled |= mDoubleTapListener.onDoubleTapEvent(ev);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mAlwaysInTapRegion) {
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int deltaX = (int) (x - mCurrentDownEvent.getX());
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int deltaY = (int) (y - mCurrentDownEvent.getY());
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int distance = (deltaX * deltaX) + (deltaY * deltaY);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (distance > mTouchSlopSquare) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mLastMotionX = x;
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mLastMotionY = y;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mAlwaysInTapRegion = false;
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mHandler.removeMessages(TAP);
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mHandler.removeMessages(SHOW_PRESS);
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mHandler.removeMessages(LONG_PRESS);
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (distance > mBiggerTouchSlopSquare) {
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mAlwaysInBiggerTapRegion = false;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1)) {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLastMotionX = x;
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLastMotionY = y;
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case MotionEvent.ACTION_UP:
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStillDown = false;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MotionEvent currentUpEvent = MotionEvent.obtain(ev);
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsDoubleTapping) {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Finally, give the up event of the double-tap
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handled |= mDoubleTapListener.onDoubleTapEvent(ev);
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mInLongPress) {
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHandler.removeMessages(TAP);
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInLongPress = false;
556f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2The Android Open Source Project            } else if (mAlwaysInTapRegion) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handled = mListener.onSingleTapUp(ev);
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // A fling must travel the minimum tap distance
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final VelocityTracker velocityTracker = mVelocityTracker;
5624296fc4d326447875c26a925f12b3935632f13bbRomain Guy                velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float velocityY = velocityTracker.getYVelocity();
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final float velocityX = velocityTracker.getXVelocity();
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((Math.abs(velocityY) > mMinimumFlingVelocity)
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || (Math.abs(velocityX) > mMinimumFlingVelocity)){
56845f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell                    handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY);
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
57145f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell            if (mPreviousUpEvent != null) {
57245f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell                mPreviousUpEvent.recycle();
57345f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell            }
57445f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell            // Hold the event we obtained above - listeners may have changed the original.
57545f2ca7f7d9fac55aa228e022f46ecbac8712a15Adam Powell            mPreviousUpEvent = currentUpEvent;
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVelocityTracker.recycle();
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVelocityTracker = null;
578b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mIsDoubleTapping = false;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.removeMessages(SHOW_PRESS);
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHandler.removeMessages(LONG_PRESS);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case MotionEvent.ACTION_CANCEL:
583216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            cancel();
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return handled;
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
588216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell    private void cancel() {
589216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        mHandler.removeMessages(SHOW_PRESS);
590216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        mHandler.removeMessages(LONG_PRESS);
591216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        mHandler.removeMessages(TAP);
592216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        mVelocityTracker.recycle();
593216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        mVelocityTracker = null;
594216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        mIsDoubleTapping = false;
595216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        mStillDown = false;
596216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        if (mInLongPress) {
597216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell            mInLongPress = false;
598216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell        }
599216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell    }
600216bccf804db9c972b317620a27de6a8adf7fbfeAdam Powell
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            MotionEvent secondDown) {
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mAlwaysInBiggerTapRegion) {
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIMEOUT) {
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int deltaX = (int) firstDown.getX() - (int) secondDown.getX();
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int deltaY = (int) firstDown.getY() - (int) secondDown.getY();
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare);
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void dispatchLongPress() {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.removeMessages(TAP);
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInLongPress = true;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mListener.onLongPress(mCurrentDownEvent);
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
622