├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── values
│ └── strings.xml
└── layout
│ └── main.xml
├── README.md
├── .classpath
├── project.properties
├── AndroidManifest.xml
├── .project
├── proguard.cfg
└── src
└── pl
└── polidea
└── gesturedetector
├── BetterGestureDetectorActivity.java
└── BetterGestureDetector.java
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polidea/better-gesture-detector/HEAD/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polidea/better-gesture-detector/HEAD/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Polidea/better-gesture-detector/HEAD/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | __This repository is no longer maintained. Issue reports and pull requests will not be attended.__
4 |
5 | ---
6 |
7 | Gesture detector for Android. It'sbetter than the default one. It's configurable and reports more events.
8 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello World, BetterGestureDetectorActivity!
5 | BetterGestureDetector
6 |
7 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-14
12 | android.library=false
13 |
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | BetterGestureDetector
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/proguard.cfg:
--------------------------------------------------------------------------------
1 | -optimizationpasses 5
2 | -dontusemixedcaseclassnames
3 | -dontskipnonpubliclibraryclasses
4 | -dontpreverify
5 | -verbose
6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7 |
8 | -keep public class * extends android.app.Activity
9 | -keep public class * extends android.app.Application
10 | -keep public class * extends android.app.Service
11 | -keep public class * extends android.content.BroadcastReceiver
12 | -keep public class * extends android.content.ContentProvider
13 | -keep public class * extends android.app.backup.BackupAgentHelper
14 | -keep public class * extends android.preference.Preference
15 | -keep public class com.android.vending.licensing.ILicensingService
16 |
17 | -keepclasseswithmembernames class * {
18 | native ;
19 | }
20 |
21 | -keepclasseswithmembers class * {
22 | public (android.content.Context, android.util.AttributeSet);
23 | }
24 |
25 | -keepclasseswithmembers class * {
26 | public (android.content.Context, android.util.AttributeSet, int);
27 | }
28 |
29 | -keepclassmembers class * extends android.app.Activity {
30 | public void *(android.view.View);
31 | }
32 |
33 | -keepclassmembers enum * {
34 | public static **[] values();
35 | public static ** valueOf(java.lang.String);
36 | }
37 |
38 | -keep class * implements android.os.Parcelable {
39 | public static final android.os.Parcelable$Creator *;
40 | }
41 |
--------------------------------------------------------------------------------
/src/pl/polidea/gesturedetector/BetterGestureDetectorActivity.java:
--------------------------------------------------------------------------------
1 | package pl.polidea.gesturedetector;
2 |
3 | import pl.polidea.gesturedetector.BetterGestureDetector.BetterGestureListener;
4 | import pl.polidea.test.R;
5 | import android.app.Activity;
6 | import android.os.Bundle;
7 | import android.view.MotionEvent;
8 | import android.widget.TextView;
9 |
10 | public class BetterGestureDetectorActivity extends Activity implements BetterGestureListener {
11 | private BetterGestureDetector gestureDetector;
12 | private TextView v;
13 |
14 | /** Called when the activity is first created. */
15 | @Override
16 | public void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.main);
19 | v = (TextView) findViewById(R.id.textView1);
20 | gestureDetector = new BetterGestureDetector(this);
21 | }
22 |
23 | @Override
24 | public boolean dispatchTouchEvent(MotionEvent ev) {
25 | gestureDetector.onTouchEvent(ev);
26 | return super.dispatchTouchEvent(ev);
27 | }
28 |
29 | @Override
30 | public void onPress(MotionEvent motionEvent) {
31 | v.setText("press");
32 | v.setBackgroundColor(0xffff0000);
33 | v.invalidate();
34 | }
35 |
36 | @Override
37 | public void onTap(MotionEvent motionEvent) {
38 | v.setText("tap");
39 | v.setBackgroundColor(0xff00ff00);
40 | v.invalidate();
41 | }
42 |
43 | @Override
44 | public void onDrag(MotionEvent motionEvent) {
45 | v.setText("drag");
46 | v.setBackgroundColor(0xff0000ff);
47 | v.invalidate();
48 | }
49 |
50 | @Override
51 | public void onMove(MotionEvent motionEvent) {
52 | v.setText("move");
53 | v.setBackgroundColor(0xffff00ff);
54 | v.invalidate();
55 | }
56 |
57 | @Override
58 | public void onRelease(MotionEvent motionEvent) {
59 | v.setText("release");
60 | v.setBackgroundColor(0xffffff00);
61 | v.invalidate();
62 | }
63 |
64 | @Override
65 | public void onLongPress(MotionEvent motionEvent) {
66 | v.setText("longpress");
67 | v.setBackgroundColor(0xff00ffff);
68 | v.invalidate();
69 | }
70 |
71 | @Override
72 | public void onMultiTap(MotionEvent motionEvent, int clicks) {
73 | v.setText("multitap [" + clicks + "]");
74 | v.setBackgroundColor(0xff7f7f7f);
75 | v.invalidate();
76 | }
77 | }
--------------------------------------------------------------------------------
/src/pl/polidea/gesturedetector/BetterGestureDetector.java:
--------------------------------------------------------------------------------
1 | package pl.polidea.gesturedetector;
2 |
3 | import android.os.Handler;
4 | import android.util.Log;
5 | import android.view.MotionEvent;
6 |
7 | // TODO: Auto-generated Javadoc
8 | /**
9 | * The Class BetterGestureDetector.
10 | */
11 | public class BetterGestureDetector {
12 |
13 | /**
14 | * The listener interface for receiving betterGesture events. The class that
15 | * is interested in processing a betterGesture event implements this
16 | * interface, and the object created with that class is registered with a
17 | * component using the component's
18 | * addBetterGestureListener method. When
19 | * the betterGesture event occurs, that object's appropriate
20 | * method is invoked.
21 | *
22 | * @see BetterGestureEvent
23 | */
24 | public interface BetterGestureListener {
25 |
26 | /**
27 | * On show press.
28 | *
29 | * @param motionEvent
30 | * the motion event
31 | */
32 | void onPress(MotionEvent motionEvent);
33 |
34 | /**
35 | * On single tap up.
36 | *
37 | * @param motionEvent
38 | * the motion event
39 | */
40 | void onTap(MotionEvent motionEvent);
41 |
42 | /**
43 | * On drag.
44 | *
45 | * @param motionEvent
46 | * the motion event
47 | */
48 | void onDrag(MotionEvent motionEvent);
49 |
50 | /**
51 | * On move.
52 | *
53 | * @param motionEvent
54 | * the motion event
55 | */
56 | void onMove(MotionEvent motionEvent);
57 |
58 | /**
59 | * On release.
60 | *
61 | * @param motionEvent
62 | * the motion event
63 | */
64 | void onRelease(MotionEvent motionEvent);
65 |
66 | /**
67 | * On long press.
68 | *
69 | * @param motionEvent
70 | * the motion event
71 | */
72 | void onLongPress(MotionEvent motionEvent);
73 |
74 | /**
75 | * On double tap.
76 | *
77 | * @param motionEvent
78 | * the motion event
79 | * @param clicks
80 | */
81 | void onMultiTap(MotionEvent motionEvent, int clicks);
82 | }
83 |
84 | /**
85 | * The Class BetterGestureAdapter.
86 | */
87 | class BetterGestureAdapter implements BetterGestureListener {
88 |
89 | /*
90 | * (non-Javadoc)
91 | *
92 | * @see
93 | * pl.polidea.test.BetterGestureDetector.BetterGestureListener#onShowPress
94 | * ()
95 | */
96 | @Override
97 | public void onPress(MotionEvent motionEvent) {
98 | // TODO Auto-generated method stub
99 |
100 | }
101 |
102 | /*
103 | * (non-Javadoc)
104 | *
105 | * @see
106 | * pl.polidea.test.BetterGestureDetector.BetterGestureListener#onSingleTapUp
107 | * ()
108 | */
109 | @Override
110 | public void onTap(MotionEvent motionEvent) {
111 | // TODO Auto-generated method stub
112 |
113 | }
114 |
115 | /*
116 | * (non-Javadoc)
117 | *
118 | * @see
119 | * pl.polidea.test.BetterGestureDetector.BetterGestureListener#onDrag()
120 | */
121 | @Override
122 | public void onDrag(MotionEvent motionEvent) {
123 | // TODO Auto-generated method stub
124 |
125 | }
126 |
127 | /*
128 | * (non-Javadoc)
129 | *
130 | * @see
131 | * pl.polidea.test.BetterGestureDetector.BetterGestureListener#onMove()
132 | */
133 | @Override
134 | public void onMove(MotionEvent motionEvent) {
135 | // TODO Auto-generated method stub
136 |
137 | }
138 |
139 | /*
140 | * (non-Javadoc)
141 | *
142 | * @see
143 | * pl.polidea.test.BetterGestureDetector.BetterGestureListener#onRelease
144 | * ()
145 | */
146 | @Override
147 | public void onRelease(MotionEvent motionEvent) {
148 | // TODO Auto-generated method stub
149 |
150 | }
151 |
152 | /*
153 | * (non-Javadoc)
154 | *
155 | * @see
156 | * pl.polidea.gesturedetector.BetterGestureDetector.BetterGestureListener
157 | * #onLongPress(android.view.MotionEvent)
158 | */
159 | @Override
160 | public void onLongPress(MotionEvent motionEvent) {
161 | // TODO Auto-generated method stub
162 |
163 | }
164 |
165 | @Override
166 | public void onMultiTap(MotionEvent motionEvent, int clicks) {
167 | // TODO Auto-generated method stub
168 |
169 | }
170 |
171 | }
172 |
173 | /** The Constant DEFAULT_PRESS_TIMEOUT. */
174 | private static final int DEFAULT_PRESS_TIMEOUT = 100;
175 |
176 | /** The Constant DEFAULT_TAP_TIMEOUT. */
177 | private static final int DEFAULT_TAP_TIMEOUT = 300;
178 |
179 | /** The Constant DEFAULT_MOVE_EPSILON. */
180 | private static final int DEFAULT_MOVE_EPSILON = 4;
181 |
182 | /** The press timeout. */
183 | private int pressTimeout = DEFAULT_PRESS_TIMEOUT;
184 |
185 | /** The tap timeout. */
186 | private int tapTimeout = DEFAULT_TAP_TIMEOUT;
187 |
188 | /** The move epsilon. */
189 | private int moveEpsilon = DEFAULT_MOVE_EPSILON;
190 |
191 | /** The handler. */
192 | private Handler handler;
193 |
194 | /** The tap handler. */
195 | Runnable tapHandler;
196 |
197 | /** The press handler. */
198 | Runnable pressHandler;
199 |
200 | /** The listener. */
201 | private final BetterGestureListener listener;
202 |
203 | /** The prev touch time. */
204 | private long prevTouchTime;
205 |
206 | /** The prev touch y. */
207 | private float prevTouchY;
208 |
209 | /** The prev touch x. */
210 | private float prevTouchX;
211 |
212 | /** The vertical move cancel. */
213 | boolean verticalMoveCancel = true;
214 |
215 | /** The horizontal move cancel. */
216 | boolean horizontalMoveCancel = true;
217 | /** The dragging. */
218 | private boolean dragging;
219 |
220 | /** The moving. */
221 | private boolean moving;
222 |
223 | /** The long press handler. */
224 | private Runnable longPressHandler;
225 |
226 | /** The long press timeout. */
227 | private long longPressTimeout = 500;
228 |
229 | private int clicks = 0;
230 |
231 | /**
232 | * Instantiates a new better gesture detector.
233 | *
234 | * @param listener
235 | * the listener
236 | */
237 | public BetterGestureDetector(BetterGestureListener listener) {
238 | if (listener == null) {
239 | throw new NullPointerException("Listener cannot be null");
240 | }
241 | this.listener = listener;
242 | handler = new Handler();
243 | }
244 |
245 | /**
246 | * On touch event.
247 | *
248 | * @param motionEvent
249 | * the motion event
250 | */
251 | public void onTouchEvent(final MotionEvent motionEvent) {
252 | float dx = motionEvent.getX() - prevTouchX;
253 | float dy = motionEvent.getY() - prevTouchY;
254 | long dt = System.currentTimeMillis() - prevTouchTime;
255 | handler.removeCallbacks(longPressHandler);
256 | longPressHandler = null;
257 |
258 | switch (motionEvent.getAction()) {
259 | case MotionEvent.ACTION_DOWN:
260 | dragging = false;
261 | moving = false;
262 | if (tapHandler != null) {
263 | clicks++;
264 | Log.e("clicks", "" + clicks);
265 | handler.removeCallbacks(tapHandler);
266 | tapHandler = null;
267 | }
268 |
269 | handler.removeCallbacks(pressHandler);
270 | pressHandler = new Runnable() {
271 |
272 | @Override
273 | public void run() {
274 | // handler.removeCallbacks(tapHandler);
275 | // tapHandler = null;
276 | onPress(motionEvent);
277 | }
278 |
279 | };
280 | handler.postDelayed(pressHandler, pressTimeout);
281 |
282 | longPressHandler = new Runnable() {
283 |
284 | @Override
285 | public void run() {
286 | onLongPress(motionEvent);
287 | }
288 | };
289 | handler.postDelayed(longPressHandler, getLongPressTimeout());
290 | prevTouchTime += dt;
291 | break;
292 | case MotionEvent.ACTION_UP:
293 | if (dt > tapTimeout || moving || dragging) {
294 | onRelease(motionEvent);
295 | break;
296 | }
297 |
298 | tapHandler = new Runnable() {
299 |
300 | @Override
301 | public void run() {
302 | handler.removeCallbacks(longPressHandler);
303 | longPressHandler = null;
304 | onTap(motionEvent, clicks);
305 | }
306 | };
307 | handler.postDelayed(tapHandler, tapTimeout - dt);
308 |
309 | prevTouchTime += dt;
310 | break;
311 |
312 | case MotionEvent.ACTION_MOVE:
313 | if (Math.abs(dx) > moveEpsilon || Math.abs(dy) > moveEpsilon || dragging || moving) {
314 | if (pressHandler == null && !moving) {
315 | dragging = true;
316 | }
317 | handler.removeCallbacks(tapHandler);
318 | tapHandler = null;
319 | handler.removeCallbacks(pressHandler);
320 | pressHandler = null;
321 | handler.removeCallbacks(longPressHandler);
322 | longPressHandler = null;
323 | moving = true;
324 | if (dragging) {
325 | onDrag(motionEvent);
326 | } else {
327 | onMove(motionEvent);
328 | }
329 | }
330 | break;
331 | case MotionEvent.ACTION_CANCEL:
332 | handler.removeCallbacks(pressHandler);
333 | pressHandler = null;
334 | handler.removeCallbacks(tapHandler);
335 | tapHandler = null;
336 | handler.removeCallbacks(longPressHandler);
337 | longPressHandler = null;
338 | onRelease(motionEvent);
339 | }
340 | prevTouchX = motionEvent.getX();
341 | prevTouchY = motionEvent.getY();
342 | }
343 |
344 | /**
345 | * On release.
346 | *
347 | * @param motionEvent
348 | * the motion event
349 | */
350 | private void onRelease(MotionEvent motionEvent) {
351 | Log.e("gesture", "release");
352 | clicks = 0;
353 | listener.onRelease(motionEvent);
354 | }
355 |
356 | /**
357 | * On drag.
358 | *
359 | * @param motionEvent
360 | * the motion event
361 | */
362 | private void onDrag(MotionEvent motionEvent) {
363 | Log.e("gesture", "drag");
364 | clicks = 0;
365 | listener.onDrag(motionEvent);
366 | }
367 |
368 | /**
369 | * On move.
370 | *
371 | * @param motionEvent
372 | * the motion event
373 | */
374 | private void onMove(MotionEvent motionEvent) {
375 | Log.e("gesture", "move");
376 | clicks = 0;
377 | listener.onMove(motionEvent);
378 | }
379 |
380 | /**
381 | * On single tap up.
382 | *
383 | * @param motionEvent
384 | * the motion event
385 | */
386 | protected void onTap(MotionEvent motionEvent, int clicks) {
387 | tapHandler = null;
388 | if (clicks == 0) {
389 | Log.e("gesture", "tap");
390 | listener.onTap(motionEvent);
391 | } else {
392 | Log.e("gesture", "multitap");
393 | listener.onMultiTap(motionEvent, clicks + 1);
394 | }
395 | this.clicks = 0;
396 | }
397 |
398 | /**
399 | * On long press.
400 | *
401 | * @param motionEvent
402 | * the motion event
403 | */
404 | protected void onLongPress(MotionEvent motionEvent) {
405 | Log.e("gesture", "longpress");
406 | clicks = 0;
407 | longPressHandler = null;
408 | listener.onLongPress(motionEvent);
409 | }
410 |
411 | /**
412 | * On show press.
413 | *
414 | * @param motionEvent
415 | * the motion event
416 | */
417 | protected void onPress(MotionEvent motionEvent) {
418 | Log.e("gesture", "press");
419 | pressHandler = null;
420 | listener.onPress(motionEvent);
421 | }
422 |
423 | /**
424 | * Gets the press timeout.
425 | *
426 | * @return the press timeout
427 | */
428 | public int getPressTimeout() {
429 | return pressTimeout;
430 | }
431 |
432 | /**
433 | * Sets the press timeout.
434 | *
435 | * @param pressTimeout
436 | * the new press timeout
437 | */
438 | public void setPressTimeout(int pressTimeout) {
439 | this.pressTimeout = pressTimeout;
440 | }
441 |
442 | /**
443 | * Gets the tap timeout.
444 | *
445 | * @return the tap timeout
446 | */
447 | public int getTapTimeout() {
448 | return tapTimeout;
449 | }
450 |
451 | /**
452 | * Sets the tap timeout.
453 | *
454 | * @param tapTimeout
455 | * the new tap timeout
456 | */
457 | public void setTapTimeout(int tapTimeout) {
458 | this.tapTimeout = tapTimeout;
459 | }
460 |
461 | /**
462 | * Gets the move epsilon.
463 | *
464 | * @return the move epsilon
465 | */
466 | public int getMoveEpsilon() {
467 | return moveEpsilon;
468 | }
469 |
470 | /**
471 | * Sets the move epsilon.
472 | *
473 | * @param moveEpsilon
474 | * the new move epsilon
475 | */
476 | public void setMoveEpsilon(int moveEpsilon) {
477 | this.moveEpsilon = moveEpsilon;
478 | }
479 |
480 | /**
481 | * Gets the long press timeout.
482 | *
483 | * @return the long press timeout
484 | */
485 | public long getLongPressTimeout() {
486 | return longPressTimeout;
487 | }
488 |
489 | /**
490 | * Sets the long press timeout.
491 | *
492 | * @param longPressTimeout
493 | * the new long press timeout
494 | */
495 | public void setLongPressTimeout(long longPressTimeout) {
496 | this.longPressTimeout = longPressTimeout;
497 | }
498 | }
499 |
--------------------------------------------------------------------------------