@@ -21,13 +21,11 @@ import android.content.Context;
|
|||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.view.GestureDetector;
|
|
||||||
|
|
||||||
import org.oscim.android.canvas.AndroidGraphics;
|
import org.oscim.android.canvas.AndroidGraphics;
|
||||||
import org.oscim.android.gl.AndroidGL;
|
import org.oscim.android.gl.AndroidGL;
|
||||||
import org.oscim.android.gl.GlConfigChooser;
|
import org.oscim.android.gl.GlConfigChooser;
|
||||||
import org.oscim.android.input.AndroidMotionEvent;
|
import org.oscim.android.input.AndroidMotionEvent;
|
||||||
import org.oscim.android.input.GestureHandler;
|
|
||||||
import org.oscim.backend.CanvasAdapter;
|
import org.oscim.backend.CanvasAdapter;
|
||||||
import org.oscim.backend.GLAdapter;
|
import org.oscim.backend.GLAdapter;
|
||||||
import org.oscim.map.Map;
|
import org.oscim.map.Map;
|
||||||
@@ -53,7 +51,6 @@ public class MapView extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected final AndroidMap mMap;
|
protected final AndroidMap mMap;
|
||||||
protected final GestureDetector mGestureDetector;
|
|
||||||
protected final AndroidMotionEvent mMotionEvent;
|
protected final AndroidMotionEvent mMotionEvent;
|
||||||
|
|
||||||
public MapView(Context context) {
|
public MapView(Context context) {
|
||||||
@@ -94,10 +91,6 @@ public class MapView extends GLSurfaceView {
|
|||||||
mMap.clearMap();
|
mMap.clearMap();
|
||||||
mMap.updateMap(false);
|
mMap.updateMap(false);
|
||||||
|
|
||||||
GestureHandler gestureHandler = new GestureHandler(mMap);
|
|
||||||
mGestureDetector = new GestureDetector(context, gestureHandler);
|
|
||||||
mGestureDetector.setOnDoubleTapListener(gestureHandler);
|
|
||||||
|
|
||||||
mMotionEvent = new AndroidMotionEvent();
|
mMotionEvent = new AndroidMotionEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,14 +109,11 @@ public class MapView extends GLSurfaceView {
|
|||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(android.view.MotionEvent motionEvent) {
|
public boolean onTouchEvent(android.view.MotionEvent motionEvent) {
|
||||||
|
|
||||||
if (!isClickable())
|
if (!isClickable())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (mGestureDetector.onTouchEvent(motionEvent))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
mMap.input.fire(null, mMotionEvent.wrap(motionEvent));
|
mMap.input.fire(null, mMotionEvent.wrap(motionEvent));
|
||||||
|
mMotionEvent.recycle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013 Hannes Janetzek
|
* Copyright 2013 Hannes Janetzek
|
||||||
|
* Copyright 2016 Andrey Novikov
|
||||||
*
|
*
|
||||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
*
|
*
|
||||||
@@ -20,10 +21,10 @@ import org.oscim.event.MotionEvent;
|
|||||||
|
|
||||||
public class AndroidMotionEvent extends MotionEvent {
|
public class AndroidMotionEvent extends MotionEvent {
|
||||||
|
|
||||||
android.view.MotionEvent mEvent;
|
private android.view.MotionEvent mEvent;
|
||||||
|
|
||||||
public MotionEvent wrap(android.view.MotionEvent e) {
|
public MotionEvent wrap(android.view.MotionEvent e) {
|
||||||
mEvent = e;
|
mEvent = android.view.MotionEvent.obtain(e);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +58,16 @@ public class AndroidMotionEvent extends MotionEvent {
|
|||||||
return mEvent.getPointerCount();
|
return mEvent.getPointerCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MotionEvent copy() {
|
||||||
|
return new AndroidMotionEvent().wrap(mEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recycle() {
|
||||||
|
mEvent.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTime() {
|
public long getTime() {
|
||||||
return mEvent.getEventTime();
|
return mEvent.getEventTime();
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013 Hannes Janetzek
|
|
||||||
* Copyright 2016 devemux86
|
|
||||||
*
|
|
||||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.android.input;
|
|
||||||
|
|
||||||
import android.view.GestureDetector.OnDoubleTapListener;
|
|
||||||
import android.view.GestureDetector.OnGestureListener;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
|
|
||||||
import org.oscim.event.Gesture;
|
|
||||||
import org.oscim.map.Map;
|
|
||||||
|
|
||||||
public class GestureHandler implements OnGestureListener, OnDoubleTapListener {
|
|
||||||
private final AndroidMotionEvent mMotionEvent;
|
|
||||||
private final Map mMap;
|
|
||||||
|
|
||||||
// Quick scale (double tap + swipe)
|
|
||||||
protected boolean quickScale;
|
|
||||||
|
|
||||||
public GestureHandler(Map map) {
|
|
||||||
mMotionEvent = new AndroidMotionEvent();
|
|
||||||
mMap = map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OnGestureListener */
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onSingleTapUp(MotionEvent e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onShowPress(MotionEvent e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLongPress(MotionEvent e) {
|
|
||||||
// Quick scale (no long press)
|
|
||||||
if (quickScale)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mMap.handleGesture(Gesture.LONG_PRESS, mMotionEvent.wrap(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onDown(MotionEvent e) {
|
|
||||||
quickScale = false;
|
|
||||||
|
|
||||||
return mMap.handleGesture(Gesture.PRESS, mMotionEvent.wrap(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OnDoubleTapListener */
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
|
||||||
return mMap.handleGesture(Gesture.TAP, mMotionEvent.wrap(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onDoubleTapEvent(MotionEvent e) {
|
|
||||||
int action = e.getActionMasked();
|
|
||||||
|
|
||||||
// Quick scale
|
|
||||||
quickScale = (action == MotionEvent.ACTION_MOVE);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onDoubleTap(MotionEvent e) {
|
|
||||||
return mMap.handleGesture(Gesture.DOUBLE_TAP, mMotionEvent.wrap(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -49,6 +49,15 @@ public class GdxMotionEvent extends MotionEvent {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MotionEvent copy() {
|
||||||
|
return new GdxMotionEvent(action, x, y, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recycle() {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTime() {
|
public long getTime() {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ import com.badlogic.gdx.InputProcessor;
|
|||||||
|
|
||||||
import org.oscim.event.MotionEvent;
|
import org.oscim.event.MotionEvent;
|
||||||
import org.oscim.map.Map;
|
import org.oscim.map.Map;
|
||||||
|
import org.oscim.utils.ArrayUtils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class MotionHandler extends MotionEvent implements InputProcessor {
|
public class MotionHandler extends MotionEvent implements InputProcessor {
|
||||||
private final Map mMap;
|
private final Map mMap;
|
||||||
@@ -77,6 +80,25 @@ public class MotionHandler extends MotionEvent implements InputProcessor {
|
|||||||
return mPointerDown;
|
return mPointerDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MotionEvent copy() {
|
||||||
|
MotionHandler handler = new MotionHandler(mMap);
|
||||||
|
handler.mPointerDown = mPointerDown;
|
||||||
|
handler.mDownTime = mDownTime;
|
||||||
|
handler.mType = mType;
|
||||||
|
handler.mPointer = mPointer;
|
||||||
|
handler.mCurX = mCurX;
|
||||||
|
handler.mCurY = mCurY;
|
||||||
|
handler.mPointerX = Arrays.copyOf(mPointerX, 10);
|
||||||
|
handler.mPointerY = Arrays.copyOf(mPointerY, 10);
|
||||||
|
handler.mTime = mTime;
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recycle() {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTime() {
|
public long getTime() {
|
||||||
return (long) (mTime / 1000000d);
|
return (long) (mTime / 1000000d);
|
||||||
|
|||||||
@@ -139,5 +139,14 @@ public class MapEventLayerTest {
|
|||||||
public int getPointerCount() {
|
public int getPointerCount() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MotionEvent copy() {
|
||||||
|
return new TestMotionEvent(action, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recycle() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013 Hannes Janetzek
|
* Copyright 2013 Hannes Janetzek
|
||||||
|
* Copyright 2016 Andrey Novikov
|
||||||
*
|
*
|
||||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
*
|
*
|
||||||
@@ -18,20 +19,28 @@ package org.oscim.event;
|
|||||||
|
|
||||||
public interface Gesture {
|
public interface Gesture {
|
||||||
|
|
||||||
static final class Press implements Gesture {
|
final class Press implements Gesture {
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class LongPress implements Gesture {
|
final class LongPress implements Gesture {
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class Tap implements Gesture {
|
final class Tap implements Gesture {
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class DoubleTap implements Gesture {
|
final class DoubleTap implements Gesture {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Gesture PRESS = new Press();
|
final class TripleTap implements Gesture {
|
||||||
public static Gesture LONG_PRESS = new LongPress();
|
}
|
||||||
public static Gesture TAP = new Tap();
|
|
||||||
public static Gesture DOUBLE_TAP = new DoubleTap();
|
class TwoFingerTap implements Gesture {
|
||||||
|
}
|
||||||
|
|
||||||
|
Gesture PRESS = new Press();
|
||||||
|
Gesture LONG_PRESS = new LongPress();
|
||||||
|
Gesture TAP = new Tap();
|
||||||
|
Gesture DOUBLE_TAP = new DoubleTap();
|
||||||
|
Gesture TRIPLE_TAP = new TripleTap();
|
||||||
|
Gesture TWO_FINGER_TAP = new TwoFingerTap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013 Hannes Janetzek
|
|
||||||
*
|
|
||||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the
|
|
||||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
|
||||||
* Foundation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.oscim.event;
|
|
||||||
|
|
||||||
import org.oscim.map.Map;
|
|
||||||
|
|
||||||
public class GestureDetector {
|
|
||||||
|
|
||||||
private final Map mMap;
|
|
||||||
|
|
||||||
public GestureDetector(Map map) {
|
|
||||||
mMap = map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onTouchEvent(MotionEvent e) {
|
|
||||||
if (e.getAction() == MotionEvent.ACTION_DOWN) {
|
|
||||||
return mMap.handleGesture(Gesture.PRESS, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -44,4 +44,7 @@ public abstract class MotionEvent {
|
|||||||
|
|
||||||
public abstract int getPointerCount();
|
public abstract int getPointerCount();
|
||||||
|
|
||||||
|
public abstract MotionEvent copy();
|
||||||
|
|
||||||
|
public abstract void recycle();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import org.oscim.core.MapPosition;
|
|||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.event.Event;
|
import org.oscim.event.Event;
|
||||||
import org.oscim.event.Gesture;
|
import org.oscim.event.Gesture;
|
||||||
import org.oscim.event.GestureListener;
|
|
||||||
import org.oscim.event.MotionEvent;
|
import org.oscim.event.MotionEvent;
|
||||||
import org.oscim.map.Map;
|
import org.oscim.map.Map;
|
||||||
import org.oscim.map.Map.InputListener;
|
import org.oscim.map.Map.InputListener;
|
||||||
@@ -30,6 +29,9 @@ import org.oscim.map.ViewController;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
import static org.oscim.backend.CanvasAdapter.dpi;
|
import static org.oscim.backend.CanvasAdapter.dpi;
|
||||||
import static org.oscim.utils.FastMath.withinSquaredDist;
|
import static org.oscim.utils.FastMath.withinSquaredDist;
|
||||||
|
|
||||||
@@ -39,9 +41,9 @@ import static org.oscim.utils.FastMath.withinSquaredDist;
|
|||||||
* TODO rewrite using gesture primitives to build more complex gestures:
|
* TODO rewrite using gesture primitives to build more complex gestures:
|
||||||
* maybe something similar to this https://github.com/ucbvislab/Proton
|
* maybe something similar to this https://github.com/ucbvislab/Proton
|
||||||
*/
|
*/
|
||||||
public class MapEventLayer extends Layer implements InputListener, GestureListener {
|
public class MapEventLayer extends Layer implements InputListener {
|
||||||
|
|
||||||
static final Logger log = LoggerFactory.getLogger(MapEventLayer.class);
|
private static final Logger log = LoggerFactory.getLogger(MapEventLayer.class);
|
||||||
|
|
||||||
private boolean mEnableRotate = true;
|
private boolean mEnableRotate = true;
|
||||||
private boolean mEnableTilt = true;
|
private boolean mEnableTilt = true;
|
||||||
@@ -60,8 +62,12 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
private boolean mDoTilt;
|
private boolean mDoTilt;
|
||||||
|
|
||||||
private boolean mDown;
|
private boolean mDown;
|
||||||
private boolean mDoubleTap;
|
|
||||||
private boolean mDragZoom;
|
private boolean mDragZoom;
|
||||||
|
private boolean mTwoFingers;
|
||||||
|
private boolean mTwoFingersDone;
|
||||||
|
private int mTaps;
|
||||||
|
private long mStartDown;
|
||||||
|
private MotionEvent mLastTap;
|
||||||
|
|
||||||
private float mPrevX1;
|
private float mPrevX1;
|
||||||
private float mPrevY1;
|
private float mPrevY1;
|
||||||
@@ -75,26 +81,38 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
/**
|
/**
|
||||||
* 2mm as minimal distance to start move: dpi / 25.4
|
* 2mm as minimal distance to start move: dpi / 25.4
|
||||||
*/
|
*/
|
||||||
protected static final float MIN_SLOP = 25.4f / 2;
|
private static final float MIN_SLOP = 25.4f / 2;
|
||||||
|
|
||||||
protected static final float PINCH_ZOOM_THRESHOLD = MIN_SLOP / 2;
|
private static final float PINCH_ZOOM_THRESHOLD = MIN_SLOP / 2;
|
||||||
protected static final float PINCH_TILT_THRESHOLD = MIN_SLOP / 2;
|
private static final float PINCH_TILT_THRESHOLD = MIN_SLOP / 2;
|
||||||
protected static final float PINCH_TILT_SLOPE = 0.75f;
|
private static final float PINCH_TILT_SLOPE = 0.75f;
|
||||||
protected static final float PINCH_ROTATE_THRESHOLD = 0.2f;
|
private static final float PINCH_ROTATE_THRESHOLD = 0.2f;
|
||||||
protected static final float PINCH_ROTATE_THRESHOLD2 = 0.5f;
|
private static final float PINCH_ROTATE_THRESHOLD2 = 0.5f;
|
||||||
|
|
||||||
|
//TODO Should be initialized with platform specific defaults
|
||||||
/**
|
/**
|
||||||
* 100 ms since start of move to reduce fling scroll
|
* 100 ms since start of move to reduce fling scroll
|
||||||
*/
|
*/
|
||||||
protected static final float FLING_MIN_THREHSHOLD = 100;
|
private static final long FLING_MIN_THRESHOLD = 100;
|
||||||
|
private static final long DOUBLE_TAP_THRESHOLD = 300;
|
||||||
|
private static final long LONG_PRESS_THRESHOLD = 500;
|
||||||
|
|
||||||
private final VelocityTracker mTracker;
|
private final VelocityTracker mTracker;
|
||||||
|
private final Timer mTimer;
|
||||||
|
private TimerTask mTimerTask;
|
||||||
|
|
||||||
private final MapPosition mapPosition = new MapPosition();
|
private final MapPosition mapPosition = new MapPosition();
|
||||||
|
|
||||||
public MapEventLayer(Map map) {
|
public MapEventLayer(Map map) {
|
||||||
super(map);
|
super(map);
|
||||||
mTracker = new VelocityTracker();
|
mTracker = new VelocityTracker();
|
||||||
|
mTimer = new Timer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetach() {
|
||||||
|
mTimer.cancel();
|
||||||
|
mTimer.purge();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -141,24 +159,58 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
mFixOnCenter = enable;
|
mFixOnCenter = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onTouchEvent(MotionEvent e) {
|
boolean onTouchEvent(final MotionEvent e) {
|
||||||
|
|
||||||
int action = getAction(e);
|
int action = getAction(e);
|
||||||
|
final long time = e.getTime();
|
||||||
|
|
||||||
if (action == MotionEvent.ACTION_DOWN) {
|
if (action == MotionEvent.ACTION_DOWN) {
|
||||||
|
if (mTimerTask != null) {
|
||||||
|
mTimerTask.cancel();
|
||||||
|
mTimer.purge();
|
||||||
|
mTimerTask = null;
|
||||||
|
}
|
||||||
|
mMap.handleGesture(Gesture.PRESS, e);
|
||||||
|
mDown = true;
|
||||||
|
mStartDown = time;
|
||||||
|
if (mTaps > 0) {
|
||||||
|
float mx = e.getX(0) - mLastTap.getX();
|
||||||
|
float my = e.getY(0) - mLastTap.getY();
|
||||||
|
if (isMinimalMove(mx, my)) {
|
||||||
|
mTaps = 0;
|
||||||
|
log.debug("tap {} {}", mLastTap.getX(), mLastTap.getY());
|
||||||
|
mMap.handleGesture(Gesture.TAP, mLastTap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
mMap.animator().cancel();
|
mMap.animator().cancel();
|
||||||
|
|
||||||
mStartMove = -1;
|
mStartMove = -1;
|
||||||
mDoubleTap = false;
|
|
||||||
mDragZoom = false;
|
mDragZoom = false;
|
||||||
|
mTwoFingers = false;
|
||||||
|
mTwoFingersDone = false;
|
||||||
|
|
||||||
|
mTimerTask = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (mTwoFingers || mStartMove != -1)
|
||||||
|
return;
|
||||||
|
mMap.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
log.debug("long press {} {}", e.getX(), e.getY());
|
||||||
|
mMap.handleGesture(Gesture.LONG_PRESS, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mTimer.schedule(mTimerTask, LONG_PRESS_THRESHOLD);
|
||||||
|
}
|
||||||
|
|
||||||
mPrevX1 = e.getX(0);
|
mPrevX1 = e.getX(0);
|
||||||
mPrevY1 = e.getY(0);
|
mPrevY1 = e.getY(0);
|
||||||
|
|
||||||
mDown = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!(mDown || mDoubleTap)) {
|
if (!mDown) {
|
||||||
/* no down event received */
|
/* no down event received */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -169,17 +221,12 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
}
|
}
|
||||||
if (action == MotionEvent.ACTION_UP) {
|
if (action == MotionEvent.ACTION_UP) {
|
||||||
mDown = false;
|
mDown = false;
|
||||||
if (mDoubleTap && !mDragZoom) {
|
if (mTimerTask != null) {
|
||||||
float pivotX = 0, pivotY = 0;
|
mTimerTask.cancel();
|
||||||
if (!mFixOnCenter) {
|
mTimer.purge();
|
||||||
pivotX = mPrevX1 - mMap.getWidth() / 2;
|
mTimerTask = null;
|
||||||
pivotY = mPrevY1 - mMap.getHeight() / 2;
|
|
||||||
}
|
}
|
||||||
|
if (mStartMove > 0) {
|
||||||
/* handle double tap zoom */
|
|
||||||
mMap.animator().animateZoom(300, 2, pivotX, pivotY);
|
|
||||||
|
|
||||||
} else if (mStartMove > 0) {
|
|
||||||
/* handle fling gesture */
|
/* handle fling gesture */
|
||||||
mTracker.update(e.getX(), e.getY(), e.getTime());
|
mTracker.update(e.getX(), e.getY(), e.getTime());
|
||||||
float vx = mTracker.getVelocityX();
|
float vx = mTracker.getVelocityX();
|
||||||
@@ -187,16 +234,86 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
|
|
||||||
/* reduce velocity for short moves */
|
/* reduce velocity for short moves */
|
||||||
float t = e.getTime() - mStartMove;
|
float t = e.getTime() - mStartMove;
|
||||||
if (t < FLING_MIN_THREHSHOLD) {
|
if (t < FLING_MIN_THRESHOLD) {
|
||||||
t = t / FLING_MIN_THREHSHOLD;
|
t = t / FLING_MIN_THRESHOLD;
|
||||||
vy *= t * t;
|
vy *= t * t;
|
||||||
vx *= t * t;
|
vx *= t * t;
|
||||||
}
|
}
|
||||||
doFling(vx, vy);
|
doFling(vx, vy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (time - mStartDown > LONG_PRESS_THRESHOLD) {
|
||||||
|
log.debug(" not a tap");
|
||||||
|
// this was not a tap
|
||||||
|
mTaps = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTaps > 0) {
|
||||||
|
if ((time - mLastTap.getTime()) >= DOUBLE_TAP_THRESHOLD) {
|
||||||
|
mTaps = 1;
|
||||||
|
log.debug("tap {} {}", mLastTap.getX(), mLastTap.getY());
|
||||||
|
mMap.handleGesture(Gesture.TAP, mLastTap);
|
||||||
|
} else {
|
||||||
|
mTaps += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mTaps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mLastTap != null) {
|
||||||
|
mLastTap.recycle();
|
||||||
|
}
|
||||||
|
mLastTap = e.copy();
|
||||||
|
|
||||||
|
if (mTaps == 3) {
|
||||||
|
mTaps = 0;
|
||||||
|
log.debug("triple tap {} {}", e.getX(), e.getY());
|
||||||
|
mMap.handleGesture(Gesture.TRIPLE_TAP, e);
|
||||||
|
} else if (mTaps == 2) {
|
||||||
|
mTimerTask = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mTaps = 0;
|
||||||
|
if (mDragZoom)
|
||||||
|
return;
|
||||||
|
mMap.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
log.debug("double tap {} {}", e.getX(), e.getY());
|
||||||
|
if (!mMap.handleGesture(Gesture.DOUBLE_TAP, e)) {
|
||||||
|
/* handle double tap zoom */
|
||||||
|
final float pivotX = mFixOnCenter ? 0 : mPrevX1 - mMap.getWidth() / 2;
|
||||||
|
final float pivotY = mFixOnCenter ? 0 : mPrevY1 - mMap.getHeight() / 2;
|
||||||
|
mMap.animator().animateZoom(300, 2, pivotX, pivotY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mTimer.schedule(mTimerTask, DOUBLE_TAP_THRESHOLD);
|
||||||
|
} else {
|
||||||
|
mTimerTask = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mTaps = 0;
|
||||||
|
if (!mTwoFingers && mStartMove == -1) {
|
||||||
|
mMap.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
log.debug("tap {} {}", e.getX(), e.getY());
|
||||||
|
mMap.handleGesture(Gesture.TAP, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mTimer.schedule(mTimerTask, DOUBLE_TAP_THRESHOLD);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (action == MotionEvent.ACTION_CANCEL) {
|
if (action == MotionEvent.ACTION_CANCEL) {
|
||||||
|
mTaps = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||||
@@ -205,6 +322,12 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (action == MotionEvent.ACTION_POINTER_UP) {
|
if (action == MotionEvent.ACTION_POINTER_UP) {
|
||||||
|
if (e.getPointerCount() == 2 && !mTwoFingersDone) {
|
||||||
|
log.debug("two finger tap");
|
||||||
|
if (!mMap.handleGesture(Gesture.TWO_FINGER_TAP, e)) {
|
||||||
|
mMap.animator().animateZoom(300, 0.5, 0f, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
updateMulti(e);
|
updateMulti(e);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -232,12 +355,7 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
mPrevY1 = y1;
|
mPrevY1 = y1;
|
||||||
|
|
||||||
/* double-tap drag zoom */
|
/* double-tap drag zoom */
|
||||||
if (mDoubleTap) {
|
if (mTaps == 1) {
|
||||||
/* just ignore first move event to set mPrevX/Y */
|
|
||||||
if (!mDown) {
|
|
||||||
mDown = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!mDragZoom && !isMinimalMove(mx, my)) {
|
if (!mDragZoom && !isMinimalMove(mx, my)) {
|
||||||
mPrevX1 -= mx;
|
mPrevX1 -= mx;
|
||||||
mPrevY1 -= my;
|
mPrevY1 -= my;
|
||||||
@@ -300,6 +418,7 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
mCanScale = false;
|
mCanScale = false;
|
||||||
mCanRotate = false;
|
mCanRotate = false;
|
||||||
mDoTilt = true;
|
mDoTilt = true;
|
||||||
|
mTwoFingersDone = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,6 +445,7 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
/* start rotate, disable tilt */
|
/* start rotate, disable tilt */
|
||||||
mDoRotate = true;
|
mDoRotate = true;
|
||||||
mCanTilt = false;
|
mCanTilt = false;
|
||||||
|
mTwoFingersDone = true;
|
||||||
|
|
||||||
mAngle = rad;
|
mAngle = rad;
|
||||||
} else if (!mDoScale) {
|
} else if (!mDoScale) {
|
||||||
@@ -345,6 +465,7 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
mDoRotate = true;
|
mDoRotate = true;
|
||||||
mCanRotate = true;
|
mCanRotate = true;
|
||||||
mAngle = rad;
|
mAngle = rad;
|
||||||
|
mTwoFingersDone = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,6 +481,7 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
|
|
||||||
mCanTilt = false;
|
mCanTilt = false;
|
||||||
mDoScale = true;
|
mDoScale = true;
|
||||||
|
mTwoFingersDone = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mDoScale || mDoRotate) {
|
if (mDoScale || mDoRotate) {
|
||||||
@@ -408,6 +530,8 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
mPrevY1 = e.getY(0);
|
mPrevY1 = e.getY(0);
|
||||||
|
|
||||||
if (cnt == 2) {
|
if (cnt == 2) {
|
||||||
|
mTwoFingers = true;
|
||||||
|
|
||||||
mDoScale = false;
|
mDoScale = false;
|
||||||
mDoRotate = false;
|
mDoRotate = false;
|
||||||
mDoTilt = false;
|
mDoTilt = false;
|
||||||
@@ -440,16 +564,7 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private static class VelocityTracker {
|
||||||
public boolean onGesture(Gesture g, MotionEvent e) {
|
|
||||||
if (g == Gesture.DOUBLE_TAP) {
|
|
||||||
mDoubleTap = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class VelocityTracker {
|
|
||||||
/* sample window, 200ms */
|
/* sample window, 200ms */
|
||||||
private static final int MAX_MS = 200;
|
private static final int MAX_MS = 200;
|
||||||
private static final int SAMPLES = 32;
|
private static final int SAMPLES = 32;
|
||||||
@@ -512,11 +627,11 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
return (float) ((amount * 1000) / duration);
|
return (float) ((amount * 1000) / duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getVelocityY() {
|
float getVelocityY() {
|
||||||
return getVelocity(mMeanY);
|
return getVelocity(mMeanY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getVelocityX() {
|
float getVelocityX() {
|
||||||
return getVelocity(mMeanX);
|
return getVelocity(mMeanX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user