1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.gallery3d.ui;
18 
19 import android.content.Context;
20 import android.os.SystemClock;
21 import android.view.GestureDetector;
22 import android.view.MotionEvent;
23 import android.view.ScaleGestureDetector;
24 
25 // This class aggregates three gesture detectors: GestureDetector,
26 // ScaleGestureDetector, and DownUpDetector.
27 public class GestureRecognizer {
28     @SuppressWarnings("unused")
29     private static final String TAG = "GestureRecognizer";
30 
31     public interface Listener {
onSingleTapUp(float x, float y)32         boolean onSingleTapUp(float x, float y);
onDoubleTap(float x, float y)33         boolean onDoubleTap(float x, float y);
onScroll(float dx, float dy, float totalX, float totalY)34         boolean onScroll(float dx, float dy, float totalX, float totalY);
onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)35         boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
onScaleBegin(float focusX, float focusY)36         boolean onScaleBegin(float focusX, float focusY);
onScale(float focusX, float focusY, float scale)37         boolean onScale(float focusX, float focusY, float scale);
onScaleEnd()38         void onScaleEnd();
onDown(float x, float y)39         void onDown(float x, float y);
onUp()40         void onUp();
41     }
42 
43     private final GestureDetector mGestureDetector;
44     private final ScaleGestureDetector mScaleDetector;
45     private final DownUpDetector mDownUpDetector;
46     private final Listener mListener;
47 
GestureRecognizer(Context context, Listener listener)48     public GestureRecognizer(Context context, Listener listener) {
49         mListener = listener;
50         mGestureDetector = new GestureDetector(context, new MyGestureListener(),
51                 null, true /* ignoreMultitouch */);
52         mScaleDetector = new ScaleGestureDetector(
53                 context, new MyScaleListener());
54         mDownUpDetector = new DownUpDetector(new MyDownUpListener());
55     }
56 
onTouchEvent(MotionEvent event)57     public void onTouchEvent(MotionEvent event) {
58         mGestureDetector.onTouchEvent(event);
59         mScaleDetector.onTouchEvent(event);
60         mDownUpDetector.onTouchEvent(event);
61     }
62 
isDown()63     public boolean isDown() {
64         return mDownUpDetector.isDown();
65     }
66 
cancelScale()67     public void cancelScale() {
68         long now = SystemClock.uptimeMillis();
69         MotionEvent cancelEvent = MotionEvent.obtain(
70                 now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
71         mScaleDetector.onTouchEvent(cancelEvent);
72         cancelEvent.recycle();
73     }
74 
75     private class MyGestureListener
76                 extends GestureDetector.SimpleOnGestureListener {
77         @Override
onSingleTapUp(MotionEvent e)78         public boolean onSingleTapUp(MotionEvent e) {
79             return mListener.onSingleTapUp(e.getX(), e.getY());
80         }
81 
82         @Override
onDoubleTap(MotionEvent e)83         public boolean onDoubleTap(MotionEvent e) {
84             return mListener.onDoubleTap(e.getX(), e.getY());
85         }
86 
87         @Override
onScroll( MotionEvent e1, MotionEvent e2, float dx, float dy)88         public boolean onScroll(
89                 MotionEvent e1, MotionEvent e2, float dx, float dy) {
90             return mListener.onScroll(
91                     dx, dy, e2.getX() - e1.getX(), e2.getY() - e1.getY());
92         }
93 
94         @Override
onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)95         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
96                 float velocityY) {
97             return mListener.onFling(e1, e2, velocityX, velocityY);
98         }
99     }
100 
101     private class MyScaleListener
102             extends ScaleGestureDetector.SimpleOnScaleGestureListener {
103         @Override
onScaleBegin(ScaleGestureDetector detector)104         public boolean onScaleBegin(ScaleGestureDetector detector) {
105             return mListener.onScaleBegin(
106                     detector.getFocusX(), detector.getFocusY());
107         }
108 
109         @Override
onScale(ScaleGestureDetector detector)110         public boolean onScale(ScaleGestureDetector detector) {
111             return mListener.onScale(detector.getFocusX(),
112                     detector.getFocusY(), detector.getScaleFactor());
113         }
114 
115         @Override
onScaleEnd(ScaleGestureDetector detector)116         public void onScaleEnd(ScaleGestureDetector detector) {
117             mListener.onScaleEnd();
118         }
119     }
120 
121     private class MyDownUpListener implements DownUpDetector.DownUpListener {
122         @Override
onDown(MotionEvent e)123         public void onDown(MotionEvent e) {
124             mListener.onDown(e.getX(), e.getY());
125         }
126 
127         @Override
onUp(MotionEvent e)128         public void onUp(MotionEvent e) {
129             mListener.onUp();
130         }
131     }
132 }
133