* [android] new gesture library - added SNAPSHOT dependency
* [android] new gesture library - cleaned up redundant classes
* [android] new gesture library - limiting scale when rotating
* [android] new gesture library - shove gesture filtering
* [android] new gesture library - increase rotation threshold when scaling
* [android] new gesture library - minimum angular velocity
* [android] new gesture library - exposed gestures execution listeners
* [android] new gesture library - notifying new listeners tests
* [android] new gesture library - removed tracking setting
* [android] new gesture library - resetting focal point with every scale/rotate callback
* [android] new gesture library - fixed camera change dispatcher callbacks
* [android] new gesture library - cancel velocity animations in maps onStop()
* [android] new gesture library - extracted telemetry pushes to a method
* [android] new gesture library - deprecated onScrollListener
* [android] new gesture library - unified shove listener name
(cherry picked from commit 7905bd6)
This commit is contained in:
@@ -3,6 +3,7 @@ apply plugin: 'com.android.library'
|
||||
dependencies {
|
||||
api dependenciesList.mapboxAndroidTelemetry
|
||||
api dependenciesList.mapboxJavaGeoJSON
|
||||
api dependenciesList.mapboxAndroidGestures
|
||||
implementation dependenciesList.supportAnnotations
|
||||
implementation dependenciesList.supportFragmentV4
|
||||
implementation dependenciesList.timber
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
|
||||
* (code.almeros.com)
|
||||
* <p>
|
||||
* All rights reserved.
|
||||
* <p>
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* <p>
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public abstract class BaseGestureDetector {
|
||||
protected final Context context;
|
||||
protected boolean gestureInProgress;
|
||||
|
||||
protected MotionEvent prevEvent;
|
||||
protected MotionEvent currEvent;
|
||||
|
||||
protected float currPressure;
|
||||
protected float prevPressure;
|
||||
protected long timeDelta;
|
||||
|
||||
/**
|
||||
* This value is the threshold ratio between the previous combined pressure
|
||||
* and the current combined pressure. When pressure decreases rapidly
|
||||
* between events the position values can often be imprecise, as it usually
|
||||
* indicates that the user is in the process of lifting a pointer off of the
|
||||
* device. This value was tuned experimentally.
|
||||
*/
|
||||
protected static final float PRESSURE_THRESHOLD = 0.67f;
|
||||
|
||||
public BaseGestureDetector(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* All gesture detectors need to be called through this method to be able to
|
||||
* detect gestures. This method delegates work to handler methods
|
||||
* (handleStartProgressEvent, handleInProgressEvent) implemented in
|
||||
* extending classes.
|
||||
*
|
||||
* @param event MotionEvent
|
||||
* @return {@code true} as handled
|
||||
*/
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
final int actionCode = event.getAction() & MotionEvent.ACTION_MASK;
|
||||
if (!gestureInProgress) {
|
||||
handleStartProgressEvent(actionCode, event);
|
||||
} else {
|
||||
handleInProgressEvent(actionCode, event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the current event occurred when NO gesture is in progress
|
||||
* yet. The handling in this implementation may set the gesture in progress
|
||||
* (via gestureInProgress) or out of progress
|
||||
*
|
||||
* @param actionCode Action Code from MotionEvent
|
||||
* @param event MotionEvent
|
||||
*/
|
||||
protected abstract void handleStartProgressEvent(int actionCode,
|
||||
MotionEvent event);
|
||||
|
||||
/**
|
||||
* Called when the current event occurred when a gesture IS in progress. The
|
||||
* handling in this implementation may set the gesture out of progress (via
|
||||
* gestureInProgress).
|
||||
*
|
||||
* @param actionCode Action Code from MotionEvent
|
||||
* @param event MotionEvent
|
||||
*/
|
||||
protected abstract void handleInProgressEvent(int actionCode,
|
||||
MotionEvent event);
|
||||
|
||||
protected void updateStateByEvent(MotionEvent curr) {
|
||||
final MotionEvent prev = prevEvent;
|
||||
|
||||
// Reset currEvent
|
||||
if (currEvent != null) {
|
||||
currEvent.recycle();
|
||||
currEvent = null;
|
||||
}
|
||||
currEvent = MotionEvent.obtain(curr);
|
||||
|
||||
// Delta time
|
||||
timeDelta = curr.getEventTime() - prev.getEventTime();
|
||||
|
||||
// Pressure
|
||||
currPressure = curr.getPressure(curr.getActionIndex());
|
||||
prevPressure = prev.getPressure(prev.getActionIndex());
|
||||
}
|
||||
|
||||
protected void resetState() {
|
||||
if (prevEvent != null) {
|
||||
prevEvent.recycle();
|
||||
prevEvent = null;
|
||||
}
|
||||
if (currEvent != null) {
|
||||
currEvent.recycle();
|
||||
currEvent = null;
|
||||
}
|
||||
gestureInProgress = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if a gesture is currently in progress.
|
||||
*
|
||||
* @return {@code true} if a gesture is currently in progress, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isInProgress() {
|
||||
return gestureInProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time difference in milliseconds between the previous accepted
|
||||
* GestureDetector event and the current GestureDetector event.
|
||||
*
|
||||
* @return Time difference since the last move event in milliseconds.
|
||||
*/
|
||||
public long getTimeDelta() {
|
||||
return timeDelta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the event time of the current GestureDetector event being
|
||||
* processed.
|
||||
*
|
||||
* @return Current GestureDetector event time in milliseconds.
|
||||
*/
|
||||
public long getEventTime() {
|
||||
return currEvent.getEventTime();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
|
||||
* (code.almeros.com)
|
||||
* <p>
|
||||
* All rights reserved.
|
||||
* <p>
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* <p>
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public class MoveGestureDetector extends BaseGestureDetector {
|
||||
|
||||
/**
|
||||
* Listener which must be implemented which is used by MoveGestureDetector
|
||||
* to perform callbacks to any implementing class which is registered to a
|
||||
* MoveGestureDetector via the constructor.
|
||||
*
|
||||
* @see MoveGestureDetector.SimpleOnMoveGestureListener
|
||||
*/
|
||||
public interface OnMoveGestureListener {
|
||||
public boolean onMove(MoveGestureDetector detector);
|
||||
|
||||
public boolean onMoveBegin(MoveGestureDetector detector);
|
||||
|
||||
public void onMoveEnd(MoveGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class which may be extended and where the methods may be
|
||||
* implemented. This way it is not necessary to implement all methods of
|
||||
* OnMoveGestureListener.
|
||||
*/
|
||||
public static class SimpleOnMoveGestureListener implements
|
||||
OnMoveGestureListener {
|
||||
public boolean onMove(MoveGestureDetector detector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onMoveBegin(MoveGestureDetector detector) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onMoveEnd(MoveGestureDetector detector) {
|
||||
// Do nothing, overridden implementation may be used
|
||||
}
|
||||
}
|
||||
|
||||
private static final PointF FOCUS_DELTA_ZERO = new PointF();
|
||||
|
||||
private final OnMoveGestureListener listener;
|
||||
|
||||
private PointF focusExternal = new PointF();
|
||||
private PointF focusDeltaExternal = new PointF();
|
||||
|
||||
public MoveGestureDetector(Context context, OnMoveGestureListener listener) {
|
||||
super(context);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
resetState(); // In case we missed an UP/CANCEL event
|
||||
|
||||
prevEvent = MotionEvent.obtain(event);
|
||||
timeDelta = 0;
|
||||
|
||||
updateStateByEvent(event);
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
gestureInProgress = listener.onMoveBegin(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleInProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
listener.onMoveEnd(this);
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
updateStateByEvent(event);
|
||||
|
||||
// Only accept the event if our relative pressure is within
|
||||
// a certain limit. This can help filter shaky data as a
|
||||
// finger is lifted.
|
||||
if (currPressure / prevPressure > PRESSURE_THRESHOLD) {
|
||||
final boolean updatePrevious = listener.onMove(this);
|
||||
if (updatePrevious) {
|
||||
prevEvent.recycle();
|
||||
prevEvent = MotionEvent.obtain(event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateStateByEvent(MotionEvent curr) {
|
||||
super.updateStateByEvent(curr);
|
||||
|
||||
final MotionEvent prev = prevEvent;
|
||||
|
||||
// Focus intenal
|
||||
PointF currFocusInternal = determineFocalPoint(curr);
|
||||
PointF prevFocusInternal = determineFocalPoint(prev);
|
||||
|
||||
// Focus external
|
||||
// - Prevent skipping of focus delta when a finger is added or removed
|
||||
boolean skipNextMoveEvent = prev.getPointerCount() != curr
|
||||
.getPointerCount();
|
||||
focusDeltaExternal = skipNextMoveEvent ? FOCUS_DELTA_ZERO
|
||||
: new PointF(currFocusInternal.x - prevFocusInternal.x,
|
||||
currFocusInternal.y - prevFocusInternal.y);
|
||||
|
||||
// - Don't directly use mFocusInternal (or skipping will occur). Add
|
||||
// unskipped delta values to focusExternal instead.
|
||||
focusExternal.x += focusDeltaExternal.x;
|
||||
focusExternal.y += focusDeltaExternal.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine (multi)finger focal point (a.k.a. center point between all
|
||||
* fingers)
|
||||
*
|
||||
* @param motionEvent a {@link MotionEvent} object.
|
||||
* @return PointF focal point
|
||||
*/
|
||||
private PointF determineFocalPoint(MotionEvent motionEvent) {
|
||||
// Number of fingers on screen
|
||||
final int pCount = motionEvent.getPointerCount();
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
for (int i = 0; i < pCount; i++) {
|
||||
x += motionEvent.getX(i);
|
||||
y += motionEvent.getY(i);
|
||||
}
|
||||
|
||||
return new PointF(x / pCount, y / pCount);
|
||||
}
|
||||
|
||||
public float getFocusX() {
|
||||
return focusExternal.x;
|
||||
}
|
||||
|
||||
public float getFocusY() {
|
||||
return focusExternal.y;
|
||||
}
|
||||
|
||||
public PointF getFocusDelta() {
|
||||
return focusDeltaExternal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
|
||||
* (code.almeros.com)
|
||||
* <p>
|
||||
* All rights reserved.
|
||||
* <p>
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* <p>
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public class RotateGestureDetector extends TwoFingerGestureDetector {
|
||||
|
||||
/**
|
||||
* Listener which must be implemented which is used by RotateGestureDetector
|
||||
* to perform callbacks to any implementing class which is registered to a
|
||||
* RotateGestureDetector via the constructor.
|
||||
*
|
||||
* @see RotateGestureDetector.SimpleOnRotateGestureListener
|
||||
*/
|
||||
public interface OnRotateGestureListener {
|
||||
public boolean onRotate(RotateGestureDetector detector);
|
||||
|
||||
public boolean onRotateBegin(RotateGestureDetector detector);
|
||||
|
||||
public void onRotateEnd(RotateGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class which may be extended and where the methods may be
|
||||
* implemented. This way it is not necessary to implement all methods of
|
||||
* OnRotateGestureListener.
|
||||
*/
|
||||
public static class SimpleOnRotateGestureListener implements
|
||||
OnRotateGestureListener {
|
||||
public boolean onRotate(RotateGestureDetector detector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onRotateBegin(RotateGestureDetector detector) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onRotateEnd(RotateGestureDetector detector) {
|
||||
// Do nothing, overridden implementation may be used
|
||||
}
|
||||
}
|
||||
|
||||
private final OnRotateGestureListener listener;
|
||||
private boolean sloppyGesture;
|
||||
|
||||
public RotateGestureDetector(Context context,
|
||||
OnRotateGestureListener listener) {
|
||||
super(context);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
// At least the second finger is on screen now
|
||||
|
||||
resetState(); // In case we missed an UP/CANCEL event
|
||||
prevEvent = MotionEvent.obtain(event);
|
||||
timeDelta = 0;
|
||||
|
||||
updateStateByEvent(event);
|
||||
|
||||
// See if we have a sloppy gesture
|
||||
sloppyGesture = isSloppyGesture(event);
|
||||
if (!sloppyGesture) {
|
||||
// No, start gesture now
|
||||
gestureInProgress = listener.onRotateBegin(this);
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!sloppyGesture) {
|
||||
break;
|
||||
}
|
||||
|
||||
// See if we still have a sloppy gesture
|
||||
sloppyGesture = isSloppyGesture(event);
|
||||
if (!sloppyGesture) {
|
||||
// No, start normal gesture now
|
||||
gestureInProgress = listener.onRotateBegin(this);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if (!sloppyGesture) {
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleInProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
// Gesture ended but
|
||||
updateStateByEvent(event);
|
||||
|
||||
if (!sloppyGesture) {
|
||||
listener.onRotateEnd(this);
|
||||
}
|
||||
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (!sloppyGesture) {
|
||||
listener.onRotateEnd(this);
|
||||
}
|
||||
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
updateStateByEvent(event);
|
||||
|
||||
// Only accept the event if our relative pressure is within
|
||||
// a certain limit. This can help filter shaky data as a
|
||||
// finger is lifted.
|
||||
if (currPressure / prevPressure > PRESSURE_THRESHOLD) {
|
||||
final boolean updatePrevious = listener.onRotate(this);
|
||||
if (updatePrevious) {
|
||||
prevEvent.recycle();
|
||||
prevEvent = MotionEvent.obtain(event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetState() {
|
||||
super.resetState();
|
||||
sloppyGesture = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rotation difference from the previous rotate event to the
|
||||
* current event.
|
||||
*
|
||||
* @return The current rotation //difference in degrees.
|
||||
*/
|
||||
public float getRotationDegreesDelta() {
|
||||
double diffRadians = Math.atan2(prevFingerDiffY, prevFingerDiffX)
|
||||
- Math.atan2(currFingerDiffY, currFingerDiffX);
|
||||
return (float) (diffRadians * 180.0 / Math.PI);
|
||||
}
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* @author Robert Nordan (robert.nordan@norkart.no)
|
||||
* <p>
|
||||
* Copyright (c) 2013, Norkart AS
|
||||
* <p>
|
||||
* All rights reserved.
|
||||
* <p>
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* <p>
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public class ShoveGestureDetector extends TwoFingerGestureDetector {
|
||||
|
||||
/**
|
||||
* Listener which must be implemented which is used by ShoveGestureDetector
|
||||
* to perform callbacks to any implementing class which is registered to a
|
||||
* ShoveGestureDetector via the constructor.
|
||||
*
|
||||
* @see ShoveGestureDetector.SimpleOnShoveGestureListener
|
||||
*/
|
||||
public interface OnShoveGestureListener {
|
||||
public boolean onShove(ShoveGestureDetector detector);
|
||||
|
||||
public boolean onShoveBegin(ShoveGestureDetector detector);
|
||||
|
||||
public void onShoveEnd(ShoveGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class which may be extended and where the methods may be
|
||||
* implemented. This way it is not necessary to implement all methods of
|
||||
* OnShoveGestureListener.
|
||||
*/
|
||||
public static class SimpleOnShoveGestureListener implements
|
||||
OnShoveGestureListener {
|
||||
public boolean onShove(ShoveGestureDetector detector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onShoveBegin(ShoveGestureDetector detector) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onShoveEnd(ShoveGestureDetector detector) {
|
||||
// Do nothing, overridden implementation may be used
|
||||
}
|
||||
}
|
||||
|
||||
private float prevAverageY;
|
||||
private float currAverageY;
|
||||
|
||||
private final OnShoveGestureListener listener;
|
||||
private boolean sloppyGesture;
|
||||
|
||||
public ShoveGestureDetector(Context context, OnShoveGestureListener listener) {
|
||||
super(context);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleStartProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
// At least the second finger is on screen now
|
||||
|
||||
resetState(); // In case we missed an UP/CANCEL event
|
||||
prevEvent = MotionEvent.obtain(event);
|
||||
timeDelta = 0;
|
||||
|
||||
updateStateByEvent(event);
|
||||
|
||||
// See if we have a sloppy gesture
|
||||
sloppyGesture = isSloppyGesture(event);
|
||||
if (!sloppyGesture) {
|
||||
// No, start gesture now
|
||||
gestureInProgress = listener.onShoveBegin(this);
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!sloppyGesture) {
|
||||
break;
|
||||
}
|
||||
|
||||
// See if we still have a sloppy gesture
|
||||
sloppyGesture = isSloppyGesture(event);
|
||||
if (!sloppyGesture) {
|
||||
// No, start normal gesture now
|
||||
gestureInProgress = listener.onShoveBegin(this);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if (!sloppyGesture) {
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleInProgressEvent(int actionCode, MotionEvent event) {
|
||||
switch (actionCode) {
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
// Gesture ended but
|
||||
updateStateByEvent(event);
|
||||
|
||||
if (!sloppyGesture) {
|
||||
listener.onShoveEnd(this);
|
||||
}
|
||||
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (!sloppyGesture) {
|
||||
listener.onShoveEnd(this);
|
||||
}
|
||||
|
||||
resetState();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
updateStateByEvent(event);
|
||||
|
||||
// Only accept the event if our relative pressure is within
|
||||
// a certain limit. This can help filter shaky data as a
|
||||
// finger is lifted. Also check that shove is meaningful.
|
||||
if (currPressure / prevPressure > PRESSURE_THRESHOLD
|
||||
&& Math.abs(getShovePixelsDelta()) > 0.5f) {
|
||||
final boolean updatePrevious = listener.onShove(this);
|
||||
if (updatePrevious) {
|
||||
prevEvent.recycle();
|
||||
prevEvent = MotionEvent.obtain(event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetState() {
|
||||
super.resetState();
|
||||
sloppyGesture = false;
|
||||
prevAverageY = 0.0f;
|
||||
currAverageY = 0.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateStateByEvent(MotionEvent curr) {
|
||||
super.updateStateByEvent(curr);
|
||||
|
||||
final MotionEvent prev = prevEvent;
|
||||
float py0 = prev.getY(0);
|
||||
float py1 = prev.getY(1);
|
||||
prevAverageY = (py0 + py1) / 2.0f;
|
||||
|
||||
float cy0 = curr.getY(0);
|
||||
float cy1 = curr.getY(1);
|
||||
currAverageY = (cy0 + cy1) / 2.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSloppyGesture(MotionEvent event) {
|
||||
boolean sloppy = super.isSloppyGesture(event);
|
||||
if (sloppy) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it's not traditionally sloppy, we check if the angle between
|
||||
// fingers
|
||||
// is acceptable.
|
||||
double angle = Math.abs(Math.atan2(currFingerDiffY, currFingerDiffX));
|
||||
// about 20 degrees, left or right
|
||||
return !((0.0f < angle && angle < 0.35f) || 2.79f < angle
|
||||
&& angle < Math.PI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the distance in pixels from the previous shove event to the
|
||||
* current event.
|
||||
*
|
||||
* @return The current distance in pixels.
|
||||
*/
|
||||
public float getShovePixelsDelta() {
|
||||
return currAverageY - prevAverageY;
|
||||
}
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
/**
|
||||
* @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie
|
||||
* (code.almeros.com)
|
||||
* <p>
|
||||
* All rights reserved.
|
||||
* <p>
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* <p>
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
public abstract class TwoFingerGestureDetector extends BaseGestureDetector {
|
||||
|
||||
private final float edgeSlop;
|
||||
|
||||
protected float prevFingerDiffX;
|
||||
protected float prevFingerDiffY;
|
||||
protected float currFingerDiffX;
|
||||
protected float currFingerDiffY;
|
||||
|
||||
private float currLen;
|
||||
private float prevLen;
|
||||
|
||||
private PointF focus;
|
||||
|
||||
public TwoFingerGestureDetector(Context context) {
|
||||
super(context);
|
||||
|
||||
ViewConfiguration config = ViewConfiguration.get(context);
|
||||
|
||||
edgeSlop = config.getScaledEdgeSlop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract void handleStartProgressEvent(int actionCode,
|
||||
MotionEvent event);
|
||||
|
||||
@Override
|
||||
protected abstract void handleInProgressEvent(int actionCode,
|
||||
MotionEvent event);
|
||||
|
||||
protected void updateStateByEvent(MotionEvent curr) {
|
||||
super.updateStateByEvent(curr);
|
||||
|
||||
final MotionEvent prev = prevEvent;
|
||||
|
||||
currLen = -1;
|
||||
prevLen = -1;
|
||||
|
||||
// Previous
|
||||
final float px0 = prev.getX(0);
|
||||
final float py0 = prev.getY(0);
|
||||
final float px1 = prev.getX(1);
|
||||
final float py1 = prev.getY(1);
|
||||
final float pvx = px1 - px0;
|
||||
final float pvy = py1 - py0;
|
||||
prevFingerDiffX = pvx;
|
||||
prevFingerDiffY = pvy;
|
||||
|
||||
// Current
|
||||
final float cx0 = curr.getX(0);
|
||||
final float cy0 = curr.getY(0);
|
||||
final float cx1 = curr.getX(1);
|
||||
final float cy1 = curr.getY(1);
|
||||
final float cvx = cx1 - cx0;
|
||||
final float cvy = cy1 - cy0;
|
||||
currFingerDiffX = cvx;
|
||||
currFingerDiffY = cvy;
|
||||
focus = determineFocalPoint(curr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current distance between the two pointers forming the gesture
|
||||
* in progress.
|
||||
*
|
||||
* @return Distance between pointers in pixels.
|
||||
*/
|
||||
public float getCurrentSpan() {
|
||||
if (currLen == -1) {
|
||||
final float cvx = currFingerDiffX;
|
||||
final float cvy = currFingerDiffY;
|
||||
currLen = (float) Math.sqrt(cvx * cvx + cvy * cvy);
|
||||
}
|
||||
return currLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the previous distance between the two pointers forming the gesture
|
||||
* in progress.
|
||||
*
|
||||
* @return Previous distance between pointers in pixels.
|
||||
*/
|
||||
public float getPreviousSpan() {
|
||||
if (prevLen == -1) {
|
||||
final float pvx = prevFingerDiffX;
|
||||
final float pvy = prevFingerDiffY;
|
||||
prevLen = (float) Math.sqrt(pvx * pvx + pvy * pvy);
|
||||
}
|
||||
return prevLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* MotionEvent has no getRawX(int) method; simulate it pending future API
|
||||
* approval.
|
||||
*
|
||||
* @param event Motion Event
|
||||
* @param pointerIndex Pointer Index
|
||||
* @return Raw x value or 0
|
||||
*/
|
||||
protected static float getRawX(MotionEvent event, int pointerIndex) {
|
||||
float offset = event.getRawX() - event.getX();
|
||||
if (pointerIndex < event.getPointerCount()) {
|
||||
return event.getX(pointerIndex) + offset;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* MotionEvent has no getRawY(int) method; simulate it pending future API
|
||||
* approval.
|
||||
*
|
||||
* @param event Motion Event
|
||||
* @param pointerIndex Pointer Index
|
||||
* @return Raw y value or 0
|
||||
*/
|
||||
protected static float getRawY(MotionEvent event, int pointerIndex) {
|
||||
float offset = event.getRawY() - event.getY();
|
||||
if (pointerIndex < event.getPointerCount()) {
|
||||
return event.getY(pointerIndex) + offset;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we have a sloppy gesture. Sloppy gestures can happen if the edge
|
||||
* of the user's hand is touching the screen, for example.
|
||||
*
|
||||
* @param event Motion Event
|
||||
* @return {@code true} if is sloppy gesture, {@code false} if not
|
||||
*/
|
||||
protected boolean isSloppyGesture(MotionEvent event) {
|
||||
// As orientation can change, query the metrics in touch down
|
||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
float rightSlopEdge = metrics.widthPixels - edgeSlop;
|
||||
float bottomSlopEdge = metrics.heightPixels - edgeSlop;
|
||||
|
||||
final float edgeSlop = this.edgeSlop;
|
||||
|
||||
final float x0 = event.getRawX();
|
||||
final float y0 = event.getRawY();
|
||||
final float x1 = getRawX(event, 1);
|
||||
final float y1 = getRawY(event, 1);
|
||||
|
||||
boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > rightSlopEdge
|
||||
|| y0 > bottomSlopEdge;
|
||||
boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > rightSlopEdge
|
||||
|| y1 > bottomSlopEdge;
|
||||
|
||||
if (p0sloppy && p1sloppy) {
|
||||
return true;
|
||||
} else if (p0sloppy) {
|
||||
return true;
|
||||
} else if (p1sloppy) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine (multi)finger focal point (a.k.a. center point between all
|
||||
* fingers)
|
||||
*
|
||||
* @param motionEvent Motion Event
|
||||
* @return PointF focal point
|
||||
*/
|
||||
public static PointF determineFocalPoint(MotionEvent motionEvent) {
|
||||
// Number of fingers on screen
|
||||
final int pCount = motionEvent.getPointerCount();
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
for (int i = 0; i < pCount; i++) {
|
||||
x += motionEvent.getX(i);
|
||||
y += motionEvent.getY(i);
|
||||
}
|
||||
|
||||
return new PointF(x / pCount, y / pCount);
|
||||
}
|
||||
|
||||
public float getFocusX() {
|
||||
return focus.x;
|
||||
}
|
||||
|
||||
public float getFocusY() {
|
||||
return focus.y;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Do not use this package. Internal use only.
|
||||
*/
|
||||
package com.almeros.android.multitouch.gesturedetectors;
|
||||
@@ -47,6 +47,31 @@ public class MapboxConstants {
|
||||
*/
|
||||
public static final long VELOCITY_THRESHOLD_IGNORE_FLING = 1000;
|
||||
|
||||
/**
|
||||
* Value by which the default rotation threshold will be increased when scaling
|
||||
*/
|
||||
public static final float ROTATION_THRESHOLD_INCREASE_WHEN_SCALING = 25f;
|
||||
|
||||
/**
|
||||
* Time within which user needs to lift fingers for velocity animation to start.
|
||||
*/
|
||||
public static final long SCHEDULED_ANIMATION_TIMEOUT = 150L;
|
||||
|
||||
/**
|
||||
* Minimum angular velocity for rotation animation
|
||||
*/
|
||||
public static final float MINIMUM_ANGULAR_VELOCITY = 1.5f;
|
||||
|
||||
/**
|
||||
* Maximum angular velocity for rotation animation
|
||||
*/
|
||||
public static final float MAXIMUM_ANGULAR_VELOCITY = 20f;
|
||||
|
||||
/**
|
||||
* Factor to calculate tilt change based on pixel change during shove gesture.
|
||||
*/
|
||||
public static final float SHOVE_PIXEL_CHANGE_FACTOR = 0.1f;
|
||||
|
||||
/**
|
||||
* The currently supported minimum zoom level.
|
||||
*/
|
||||
@@ -78,14 +103,14 @@ public class MapboxConstants {
|
||||
public static final double MINIMUM_DIRECTION = 0;
|
||||
|
||||
/**
|
||||
* The currently used minimun scale factor to clamp to when a quick zoom gesture occurs
|
||||
* The currently used minimum scale factor to clamp to when a quick zoom gesture occurs
|
||||
*/
|
||||
public static final float MINIMUM_SCALE_FACTOR_CLAMP = 0.00f;
|
||||
|
||||
/**
|
||||
* The currently used maximum scale factor to clamp to when a quick zoom gesture occurs
|
||||
*/
|
||||
public static final float MAXIMUM_SCALE_FACTOR_CLAMP = 0.45f;
|
||||
public static final float MAXIMUM_SCALE_FACTOR_CLAMP = 0.15f;
|
||||
|
||||
/**
|
||||
* Fragment Argument Key for MapboxMapOptions
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -128,7 +128,7 @@ final class MapKeyListener {
|
||||
|
||||
// Zoom out
|
||||
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
||||
transform.zoom(false, focalPoint);
|
||||
transform.zoomOut(focalPoint);
|
||||
return true;
|
||||
|
||||
default:
|
||||
@@ -164,7 +164,7 @@ final class MapKeyListener {
|
||||
|
||||
// Zoom in
|
||||
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
||||
transform.zoom(true, focalPoint);
|
||||
transform.zoomIn(focalPoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ final class MapKeyListener {
|
||||
if (currentTrackballLongPressTimeOut != null) {
|
||||
// Zoom in
|
||||
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
||||
transform.zoom(true, focalPoint);
|
||||
transform.zoomIn(focalPoint);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -261,7 +261,7 @@ final class MapKeyListener {
|
||||
if (!cancelled) {
|
||||
// Zoom out
|
||||
PointF pointF = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
||||
transform.zoom(false, pointF);
|
||||
transform.zoomOut(pointF);
|
||||
|
||||
// Ensure the up action is not run
|
||||
currentTrackballLongPressTimeOut = null;
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ZoomButtonsController;
|
||||
|
||||
import com.mapbox.android.gestures.AndroidGesturesManager;
|
||||
import com.mapbox.android.telemetry.AppUserTurnstile;
|
||||
import com.mapbox.android.telemetry.Event;
|
||||
import com.mapbox.android.telemetry.MapEventFactory;
|
||||
@@ -42,8 +43,6 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
|
||||
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
|
||||
import com.mapbox.mapboxsdk.storage.FileSource;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -52,6 +51,9 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
|
||||
@@ -149,7 +151,7 @@ public class MapView extends FrameLayout {
|
||||
focalPointInvalidator.addListener(createFocalPointChangeListener());
|
||||
|
||||
// callback for registering touch listeners
|
||||
RegisterTouchListener registerTouchListener = new RegisterTouchListener();
|
||||
GesturesManagerInteractionListener registerTouchListener = new GesturesManagerInteractionListener();
|
||||
|
||||
// callback for zooming in the camera
|
||||
CameraZoomInvalidator zoomInvalidator = new CameraZoomInvalidator();
|
||||
@@ -184,7 +186,7 @@ public class MapView extends FrameLayout {
|
||||
mapCallback.attachMapboxMap(mapboxMap);
|
||||
|
||||
// user input
|
||||
mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings,
|
||||
mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings,
|
||||
annotationManager, cameraChangeDispatcher);
|
||||
mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings);
|
||||
|
||||
@@ -390,6 +392,7 @@ public class MapView extends FrameLayout {
|
||||
public void onStop() {
|
||||
if (mapboxMap != null) {
|
||||
// map was destroyed before it was started
|
||||
mapGestureDetector.cancelAnimators();
|
||||
mapboxMap.onStop();
|
||||
}
|
||||
|
||||
@@ -923,7 +926,7 @@ public class MapView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private class RegisterTouchListener implements MapboxMap.OnRegisterTouchListener {
|
||||
private class GesturesManagerInteractionListener implements MapboxMap.OnGesturesManagerInteractionListener {
|
||||
|
||||
@Override
|
||||
public void onSetMapClickListener(MapboxMap.OnMapClickListener listener) {
|
||||
@@ -984,6 +987,56 @@ public class MapView extends FrameLayout {
|
||||
public void onRemoveFlingListener(MapboxMap.OnFlingListener listener) {
|
||||
mapGestureDetector.removeOnFlingListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAddMoveListener(MapboxMap.OnMoveListener listener) {
|
||||
mapGestureDetector.addOnMoveListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoveMoveListener(MapboxMap.OnMoveListener listener) {
|
||||
mapGestureDetector.removeOnMoveListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAddRotateListener(MapboxMap.OnRotateListener listener) {
|
||||
mapGestureDetector.addOnRotateListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoveRotateListener(MapboxMap.OnRotateListener listener) {
|
||||
mapGestureDetector.removeOnRotateListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAddScaleListener(MapboxMap.OnScaleListener listener) {
|
||||
mapGestureDetector.addOnScaleListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoveScaleListener(MapboxMap.OnScaleListener listener) {
|
||||
mapGestureDetector.removeOnScaleListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAddShoveListener(MapboxMap.OnShoveListener listener) {
|
||||
mapGestureDetector.addShoveListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoveShoveListener(MapboxMap.OnShoveListener listener) {
|
||||
mapGestureDetector.removeShoveListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AndroidGesturesManager getGesturesManager() {
|
||||
return mapGestureDetector.getGesturesManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGesturesManager(AndroidGesturesManager gesturesManager) {
|
||||
mapGestureDetector.setGesturesManager(gesturesManager);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MapZoomControllerListener implements ZoomButtonsController.OnZoomListener {
|
||||
@@ -1021,11 +1074,13 @@ public class MapView extends FrameLayout {
|
||||
}
|
||||
|
||||
private void onZoom(boolean zoomIn, @Nullable PointF focalPoint) {
|
||||
if (focalPoint != null) {
|
||||
transform.zoom(zoomIn, focalPoint);
|
||||
if (focalPoint == null) {
|
||||
focalPoint = new PointF(mapWidth / 2, mapHeight / 2);
|
||||
}
|
||||
if (zoomIn) {
|
||||
transform.zoomIn(focalPoint);
|
||||
} else {
|
||||
PointF centerPoint = new PointF(mapWidth / 2, mapHeight / 2);
|
||||
transform.zoom(zoomIn, centerPoint);
|
||||
transform.zoomOut(focalPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,11 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.mapbox.android.core.location.LocationEngine;
|
||||
import com.mapbox.android.gestures.AndroidGesturesManager;
|
||||
import com.mapbox.android.gestures.MoveGestureDetector;
|
||||
import com.mapbox.android.gestures.RotateGestureDetector;
|
||||
import com.mapbox.android.gestures.ShoveGestureDetector;
|
||||
import com.mapbox.android.gestures.StandardScaleGestureDetector;
|
||||
import com.mapbox.geojson.Feature;
|
||||
import com.mapbox.geojson.Geometry;
|
||||
import com.mapbox.mapboxsdk.annotations.Annotation;
|
||||
@@ -73,13 +78,13 @@ public final class MapboxMap {
|
||||
private final MyLocationViewSettings myLocationViewSettings;
|
||||
private final CameraChangeDispatcher cameraChangeDispatcher;
|
||||
|
||||
private final OnRegisterTouchListener onRegisterTouchListener;
|
||||
private final OnGesturesManagerInteractionListener onGesturesManagerInteractionListener;
|
||||
|
||||
private MapboxMap.OnFpsChangedListener onFpsChangedListener;
|
||||
private PointF focalPoint;
|
||||
|
||||
MapboxMap(NativeMapView map, Transform transform, UiSettings ui, TrackingSettings tracking,
|
||||
MyLocationViewSettings myLocationView, Projection projection, OnRegisterTouchListener listener,
|
||||
MyLocationViewSettings myLocationView, Projection projection, OnGesturesManagerInteractionListener listener,
|
||||
AnnotationManager annotations, CameraChangeDispatcher cameraChangeDispatcher) {
|
||||
this.nativeMapView = map;
|
||||
this.uiSettings = ui;
|
||||
@@ -88,7 +93,7 @@ public final class MapboxMap {
|
||||
this.myLocationViewSettings = myLocationView;
|
||||
this.annotationManager = annotations.bind(this);
|
||||
this.transform = transform;
|
||||
this.onRegisterTouchListener = listener;
|
||||
this.onGesturesManagerInteractionListener = listener;
|
||||
this.cameraChangeDispatcher = cameraChangeDispatcher;
|
||||
}
|
||||
|
||||
@@ -1845,7 +1850,7 @@ public final class MapboxMap {
|
||||
*/
|
||||
@Deprecated
|
||||
public void setOnScrollListener(@Nullable OnScrollListener listener) {
|
||||
onRegisterTouchListener.onSetScrollListener(listener);
|
||||
onGesturesManagerInteractionListener.onSetScrollListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1855,7 +1860,7 @@ public final class MapboxMap {
|
||||
* To unset the callback, use null.
|
||||
*/
|
||||
public void addOnScrollListener(@Nullable OnScrollListener listener) {
|
||||
onRegisterTouchListener.onAddScrollListener(listener);
|
||||
onGesturesManagerInteractionListener.onAddScrollListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1865,7 +1870,7 @@ public final class MapboxMap {
|
||||
* To unset the callback, use null.
|
||||
*/
|
||||
public void removeOnScrollListener(@Nullable OnScrollListener listener) {
|
||||
onRegisterTouchListener.onRemoveScrollListener(listener);
|
||||
onGesturesManagerInteractionListener.onRemoveScrollListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1877,7 +1882,7 @@ public final class MapboxMap {
|
||||
*/
|
||||
@Deprecated
|
||||
public void setOnFlingListener(@Nullable OnFlingListener listener) {
|
||||
onRegisterTouchListener.onSetFlingListener(listener);
|
||||
onGesturesManagerInteractionListener.onSetFlingListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1887,7 +1892,7 @@ public final class MapboxMap {
|
||||
* To unset the callback, use null.
|
||||
*/
|
||||
public void addOnFlingListener(@Nullable OnFlingListener listener) {
|
||||
onRegisterTouchListener.onAddFlingListener(listener);
|
||||
onGesturesManagerInteractionListener.onAddFlingListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1897,7 +1902,98 @@ public final class MapboxMap {
|
||||
* To unset the callback, use null.
|
||||
*/
|
||||
public void removeOnFlingListener(@Nullable OnFlingListener listener) {
|
||||
onRegisterTouchListener.onRemoveFlingListener(listener);
|
||||
onGesturesManagerInteractionListener.onRemoveFlingListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a callback that's invoked when the map is moved.
|
||||
*
|
||||
* @param listener The callback that's invoked when the map is moved.
|
||||
*/
|
||||
public void addOnMoveListener(OnMoveListener listener) {
|
||||
onGesturesManagerInteractionListener.onAddMoveListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked when the map is moved.
|
||||
*
|
||||
* @param listener The callback that's invoked when the map is moved.
|
||||
*/
|
||||
public void removeOnMoveListener(OnMoveListener listener) {
|
||||
onGesturesManagerInteractionListener.onRemoveMoveListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a callback that's invoked when the map is rotated.
|
||||
*
|
||||
* @param listener The callback that's invoked when the map is rotated.
|
||||
*/
|
||||
public void addOnRotateListener(OnRotateListener listener) {
|
||||
onGesturesManagerInteractionListener.onAddRotateListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked when the map is rotated.
|
||||
*
|
||||
* @param listener The callback that's invoked when the map is rotated.
|
||||
*/
|
||||
public void removeOnRotateListener(OnRotateListener listener) {
|
||||
onGesturesManagerInteractionListener.onRemoveRotateListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a callback that's invoked when the map is scaled.
|
||||
*
|
||||
* @param listener The callback that's invoked when the map is scaled.
|
||||
*/
|
||||
public void addOnScaleListener(OnScaleListener listener) {
|
||||
onGesturesManagerInteractionListener.onAddScaleListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked when the map is scaled.
|
||||
*
|
||||
* @param listener The callback that's invoked when the map is scaled.
|
||||
*/
|
||||
public void removeOnScaleListener(OnScaleListener listener) {
|
||||
onGesturesManagerInteractionListener.onRemoveScaleListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a callback that's invoked when the map is tilted.
|
||||
*
|
||||
* @param listener The callback that's invoked when the map is tilted.
|
||||
*/
|
||||
public void addOnShoveListener(OnShoveListener listener) {
|
||||
onGesturesManagerInteractionListener.onAddShoveListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a callback that's invoked when the map is tilted.
|
||||
*
|
||||
* @param listener The callback that's invoked when the map is tilted.
|
||||
*/
|
||||
public void removeOnShoveListener(OnShoveListener listener) {
|
||||
onGesturesManagerInteractionListener.onRemoveShoveListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom {@link AndroidGesturesManager} to handle {@link android.view.MotionEvent}s registered by the map.
|
||||
*
|
||||
* @param androidGesturesManager Gestures manager that interprets gestures based on the motion events.
|
||||
* @see <a href="https://github.com/mapbox/mapbox-gestures-android">mapbox-gestures-android library</a>
|
||||
*/
|
||||
public void setGesturesManager(AndroidGesturesManager androidGesturesManager) {
|
||||
onGesturesManagerInteractionListener.setGesturesManager(androidGesturesManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current {@link AndroidGesturesManager} that handles {@link android.view.MotionEvent}s registered by the map.
|
||||
*
|
||||
* @return Current gestures manager.
|
||||
*/
|
||||
public AndroidGesturesManager getGesturesManager() {
|
||||
return onGesturesManagerInteractionListener.getGesturesManager();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1909,7 +2005,7 @@ public final class MapboxMap {
|
||||
*/
|
||||
@Deprecated
|
||||
public void setOnMapClickListener(@Nullable OnMapClickListener listener) {
|
||||
onRegisterTouchListener.onSetMapClickListener(listener);
|
||||
onGesturesManagerInteractionListener.onSetMapClickListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1919,7 +2015,7 @@ public final class MapboxMap {
|
||||
* To unset the callback, use null.
|
||||
*/
|
||||
public void addOnMapClickListener(@Nullable OnMapClickListener listener) {
|
||||
onRegisterTouchListener.onAddMapClickListener(listener);
|
||||
onGesturesManagerInteractionListener.onAddMapClickListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1929,7 +2025,7 @@ public final class MapboxMap {
|
||||
* To unset the callback, use null.
|
||||
*/
|
||||
public void removeOnMapClickListener(@Nullable OnMapClickListener listener) {
|
||||
onRegisterTouchListener.onRemoveMapClickListener(listener);
|
||||
onGesturesManagerInteractionListener.onRemoveMapClickListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1941,7 +2037,7 @@ public final class MapboxMap {
|
||||
*/
|
||||
@Deprecated
|
||||
public void setOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
|
||||
onRegisterTouchListener.onSetMapLongClickListener(listener);
|
||||
onGesturesManagerInteractionListener.onSetMapLongClickListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1951,7 +2047,7 @@ public final class MapboxMap {
|
||||
* To unset the callback, use null.
|
||||
*/
|
||||
public void addOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
|
||||
onRegisterTouchListener.onAddMapLongClickListener(listener);
|
||||
onGesturesManagerInteractionListener.onAddMapLongClickListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1961,7 +2057,7 @@ public final class MapboxMap {
|
||||
* To unset the callback, use null.
|
||||
*/
|
||||
public void removeOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
|
||||
onRegisterTouchListener.onRemoveMapLongClickListener(listener);
|
||||
onGesturesManagerInteractionListener.onRemoveMapLongClickListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2220,7 +2316,9 @@ public final class MapboxMap {
|
||||
* Interface definition for a callback to be invoked when the map is scrolled.
|
||||
*
|
||||
* @see MapboxMap#setOnScrollListener(OnScrollListener)
|
||||
* @deprecated Use {@link OnMoveListener} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface OnScrollListener {
|
||||
/**
|
||||
* Called when the map is scrolled.
|
||||
@@ -2228,6 +2326,58 @@ public final class MapboxMap {
|
||||
void onScroll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the map is moved.
|
||||
*
|
||||
* @see MapboxMap#addOnMoveListener(OnMoveListener)
|
||||
*/
|
||||
public interface OnMoveListener {
|
||||
void onMoveBegin(MoveGestureDetector detector);
|
||||
|
||||
void onMove(MoveGestureDetector detector);
|
||||
|
||||
void onMoveEnd(MoveGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the map is rotated.
|
||||
*
|
||||
* @see MapboxMap#addOnRotateListener(OnRotateListener)
|
||||
*/
|
||||
public interface OnRotateListener {
|
||||
void onRotateBegin(RotateGestureDetector detector);
|
||||
|
||||
void onRotate(RotateGestureDetector detector);
|
||||
|
||||
void onRotateEnd(RotateGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the map is scaled.
|
||||
*
|
||||
* @see MapboxMap#addOnScaleListener(OnScaleListener)
|
||||
*/
|
||||
public interface OnScaleListener {
|
||||
void onScaleBegin(StandardScaleGestureDetector detector);
|
||||
|
||||
void onScale(StandardScaleGestureDetector detector);
|
||||
|
||||
void onScaleEnd(StandardScaleGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the map is tilted.
|
||||
*
|
||||
* @see MapboxMap#addOnShoveListener(OnShoveListener)
|
||||
*/
|
||||
public interface OnShoveListener {
|
||||
void onShoveBegin(ShoveGestureDetector detector);
|
||||
|
||||
void onShove(ShoveGestureDetector detector);
|
||||
|
||||
void onShoveEnd(ShoveGestureDetector detector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the camera changes position.
|
||||
*
|
||||
@@ -2330,7 +2480,7 @@ public final class MapboxMap {
|
||||
* Interface definition for a callback to be invoked when a user registers an listener that is
|
||||
* related to touch and click events.
|
||||
*/
|
||||
interface OnRegisterTouchListener {
|
||||
interface OnGesturesManagerInteractionListener {
|
||||
void onSetMapClickListener(OnMapClickListener listener);
|
||||
|
||||
void onAddMapClickListener(OnMapClickListener listener);
|
||||
@@ -2354,6 +2504,26 @@ public final class MapboxMap {
|
||||
void onAddFlingListener(OnFlingListener listener);
|
||||
|
||||
void onRemoveFlingListener(OnFlingListener listener);
|
||||
|
||||
void onAddMoveListener(OnMoveListener listener);
|
||||
|
||||
void onRemoveMoveListener(OnMoveListener listener);
|
||||
|
||||
void onAddRotateListener(OnRotateListener listener);
|
||||
|
||||
void onRemoveRotateListener(OnRotateListener listener);
|
||||
|
||||
void onAddScaleListener(OnScaleListener listener);
|
||||
|
||||
void onRemoveScaleListener(OnScaleListener listener);
|
||||
|
||||
void onAddShoveListener(OnShoveListener listener);
|
||||
|
||||
void onRemoveShoveListener(OnShoveListener listener);
|
||||
|
||||
AndroidGesturesManager getGesturesManager();
|
||||
|
||||
void setGesturesManager(AndroidGesturesManager gesturesManager);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -205,6 +205,8 @@ final class Transform implements MapView.OnMapChangedListener {
|
||||
|
||||
// cancel ongoing transitions
|
||||
mapView.cancelTransitions();
|
||||
|
||||
cameraChangeDispatcher.onCameraIdle();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@@ -235,39 +237,37 @@ final class Transform implements MapView.OnMapChangedListener {
|
||||
return mapView.getZoom();
|
||||
}
|
||||
|
||||
void zoom(boolean zoomIn, @NonNull PointF focalPoint) {
|
||||
void zoomIn(@NonNull PointF focalPoint) {
|
||||
CameraPosition cameraPosition = invalidateCameraPosition();
|
||||
if (cameraPosition != null) {
|
||||
int newZoom = (int) Math.round(cameraPosition.zoom + (zoomIn ? 1 : -1));
|
||||
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION, false);
|
||||
} else {
|
||||
// we are not transforming, notify about being idle
|
||||
cameraChangeDispatcher.onCameraIdle();
|
||||
int newZoom = (int) Math.round(cameraPosition.zoom + 1);
|
||||
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
void zoom(double zoomAddition, @NonNull PointF focalPoint, long duration) {
|
||||
void zoomOut(@NonNull PointF focalPoint) {
|
||||
CameraPosition cameraPosition = invalidateCameraPosition();
|
||||
if (cameraPosition != null) {
|
||||
int newZoom = (int) Math.round(cameraPosition.zoom + zoomAddition);
|
||||
setZoom(newZoom, focalPoint, duration, false);
|
||||
} else {
|
||||
// we are not transforming, notify about being idle
|
||||
cameraChangeDispatcher.onCameraIdle();
|
||||
int newZoom = (int) Math.round(cameraPosition.zoom - 1);
|
||||
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
void zoomBy(double zoomAddition, @NonNull PointF focalPoint) {
|
||||
setZoom(mapView.getZoom() + zoomAddition, focalPoint, 0);
|
||||
}
|
||||
|
||||
void setZoom(double zoom, @NonNull PointF focalPoint) {
|
||||
setZoom(zoom, focalPoint, 0, false);
|
||||
setZoom(zoom, focalPoint, 0);
|
||||
}
|
||||
|
||||
void setZoom(double zoom, @NonNull PointF focalPoint, long duration, final boolean isAnimator) {
|
||||
void setZoom(double zoom, @NonNull PointF focalPoint, long duration) {
|
||||
if (mapView != null) {
|
||||
mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
|
||||
@Override
|
||||
public void onMapChanged(int change) {
|
||||
if (change == MapView.REGION_DID_CHANGE_ANIMATED) {
|
||||
if (!isAnimator) {
|
||||
if (duration > 0) {
|
||||
cameraChangeDispatcher.onCameraIdle();
|
||||
}
|
||||
mapView.removeOnMapChangedListener(this);
|
||||
@@ -361,10 +361,6 @@ final class Transform implements MapView.OnMapChangedListener {
|
||||
}
|
||||
}
|
||||
|
||||
void zoomBy(double z, float x, float y) {
|
||||
mapView.setZoom(mapView.getZoom() + z, new PointF(x, y), 0);
|
||||
}
|
||||
|
||||
void moveBy(double offsetX, double offsetY, long duration) {
|
||||
if (duration > 0) {
|
||||
mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
|
||||
|
||||
@@ -6,4 +6,13 @@
|
||||
<dimen name="mapbox_eight_dp">8dp</dimen>
|
||||
<dimen name="mapbox_ninety_two_dp">92dp</dimen>
|
||||
<dimen name="mapbox_my_locationview_outer_circle">18dp</dimen>
|
||||
|
||||
<!--Minimum scale velocity required to start animation-->
|
||||
<dimen name="mapbox_minimum_scale_velocity">150dp</dimen>
|
||||
|
||||
<!--Minimum scale span delta required to execute scale gesture when rotating-->
|
||||
<dimen name="mapbox_minimum_scale_span_when_rotating">100dp</dimen>
|
||||
|
||||
<!--Minimum angular velocity required to start rotation animation-->
|
||||
<dimen name="mapbox_minimum_angular_velocity">0.025dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -2,8 +2,13 @@ package com.mapbox.mapboxsdk.maps;
|
||||
|
||||
import android.graphics.PointF;
|
||||
|
||||
import com.mapbox.android.gestures.MoveGestureDetector;
|
||||
import com.mapbox.android.gestures.RotateGestureDetector;
|
||||
import com.mapbox.android.gestures.ShoveGestureDetector;
|
||||
import com.mapbox.android.gestures.StandardScaleGestureDetector;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -13,16 +18,23 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
public class MapTouchListenersTest {
|
||||
|
||||
@Test
|
||||
public void onMapClickListenerTest() throws Exception {
|
||||
LatLng latLng = new LatLng();
|
||||
PointF pointF = new PointF();
|
||||
private MapGestureDetector mapGestureDetector;
|
||||
private LatLng latLng;
|
||||
private PointF pointF;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
latLng = new LatLng();
|
||||
pointF = new PointF();
|
||||
|
||||
Projection projection = mock(Projection.class);
|
||||
when(projection.fromScreenLocation(pointF)).thenReturn(latLng);
|
||||
MapGestureDetector mapGestureDetector = new MapGestureDetector(null,
|
||||
null, projection, null, null, null, null);
|
||||
mapGestureDetector = new MapGestureDetector(null,
|
||||
null, projection, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMapClickListenerTest() throws Exception {
|
||||
MapboxMap.OnMapClickListener listener = mock(MapboxMap.OnMapClickListener.class);
|
||||
mapGestureDetector.addOnMapClickListener(listener);
|
||||
mapGestureDetector.notifyOnMapClickListeners(pointF);
|
||||
@@ -35,14 +47,6 @@ public class MapTouchListenersTest {
|
||||
|
||||
@Test
|
||||
public void onMapLongClickListenerTest() throws Exception {
|
||||
LatLng latLng = new LatLng();
|
||||
PointF pointF = new PointF();
|
||||
|
||||
Projection projection = mock(Projection.class);
|
||||
when(projection.fromScreenLocation(pointF)).thenReturn(latLng);
|
||||
MapGestureDetector mapGestureDetector = new MapGestureDetector(null,
|
||||
null, projection, null, null, null, null);
|
||||
|
||||
MapboxMap.OnMapLongClickListener listener = mock(MapboxMap.OnMapLongClickListener.class);
|
||||
mapGestureDetector.addOnMapLongClickListener(listener);
|
||||
mapGestureDetector.notifyOnMapLongClickListeners(pointF);
|
||||
@@ -55,14 +59,6 @@ public class MapTouchListenersTest {
|
||||
|
||||
@Test
|
||||
public void onFlingListenerTest() throws Exception {
|
||||
LatLng latLng = new LatLng();
|
||||
PointF pointF = new PointF();
|
||||
|
||||
Projection projection = mock(Projection.class);
|
||||
when(projection.fromScreenLocation(pointF)).thenReturn(latLng);
|
||||
MapGestureDetector mapGestureDetector = new MapGestureDetector(null,
|
||||
null, projection, null, null, null, null);
|
||||
|
||||
MapboxMap.OnFlingListener listener = mock(MapboxMap.OnFlingListener.class);
|
||||
mapGestureDetector.addOnFlingListener(listener);
|
||||
mapGestureDetector.notifyOnFlingListeners();
|
||||
@@ -75,14 +71,6 @@ public class MapTouchListenersTest {
|
||||
|
||||
@Test
|
||||
public void onScrollListenerTest() throws Exception {
|
||||
LatLng latLng = new LatLng();
|
||||
PointF pointF = new PointF();
|
||||
|
||||
Projection projection = mock(Projection.class);
|
||||
when(projection.fromScreenLocation(pointF)).thenReturn(latLng);
|
||||
MapGestureDetector mapGestureDetector = new MapGestureDetector(null,
|
||||
null, projection, null, null, null, null);
|
||||
|
||||
MapboxMap.OnScrollListener listener = mock(MapboxMap.OnScrollListener.class);
|
||||
mapGestureDetector.addOnScrollListener(listener);
|
||||
mapGestureDetector.notifyOnScrollListeners();
|
||||
@@ -92,4 +80,88 @@ public class MapTouchListenersTest {
|
||||
mapGestureDetector.notifyOnScrollListeners();
|
||||
verify(listener, times(1)).onScroll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onMoveListenerTest() throws Exception {
|
||||
MapboxMap.OnMoveListener listener = mock(MapboxMap.OnMoveListener.class);
|
||||
MoveGestureDetector detector = mock(MoveGestureDetector.class);
|
||||
mapGestureDetector.addOnMoveListener(listener);
|
||||
mapGestureDetector.notifyOnMoveBeginListeners(detector);
|
||||
mapGestureDetector.notifyOnMoveListeners(detector);
|
||||
mapGestureDetector.notifyOnMoveEndListeners(detector);
|
||||
verify(listener, times(1)).onMoveBegin(detector);
|
||||
verify(listener, times(1)).onMove(detector);
|
||||
verify(listener, times(1)).onMoveEnd(detector);
|
||||
|
||||
mapGestureDetector.removeOnMoveListener(listener);
|
||||
mapGestureDetector.notifyOnMoveBeginListeners(detector);
|
||||
mapGestureDetector.notifyOnMoveListeners(detector);
|
||||
mapGestureDetector.notifyOnMoveEndListeners(detector);
|
||||
verify(listener, times(1)).onMoveBegin(detector);
|
||||
verify(listener, times(1)).onMove(detector);
|
||||
verify(listener, times(1)).onMoveEnd(detector);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onRotateListenerTest() throws Exception {
|
||||
MapboxMap.OnRotateListener listener = mock(MapboxMap.OnRotateListener.class);
|
||||
RotateGestureDetector detector = mock(RotateGestureDetector.class);
|
||||
mapGestureDetector.addOnRotateListener(listener);
|
||||
mapGestureDetector.notifyOnRotateBeginListeners(detector);
|
||||
mapGestureDetector.notifyOnRotateListeners(detector);
|
||||
mapGestureDetector.notifyOnRotateEndListeners(detector);
|
||||
verify(listener, times(1)).onRotateBegin(detector);
|
||||
verify(listener, times(1)).onRotate(detector);
|
||||
verify(listener, times(1)).onRotateEnd(detector);
|
||||
|
||||
mapGestureDetector.removeOnRotateListener(listener);
|
||||
mapGestureDetector.notifyOnRotateBeginListeners(detector);
|
||||
mapGestureDetector.notifyOnRotateListeners(detector);
|
||||
mapGestureDetector.notifyOnRotateEndListeners(detector);
|
||||
verify(listener, times(1)).onRotateBegin(detector);
|
||||
verify(listener, times(1)).onRotate(detector);
|
||||
verify(listener, times(1)).onRotateEnd(detector);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onScaleListenerTest() throws Exception {
|
||||
MapboxMap.OnScaleListener listener = mock(MapboxMap.OnScaleListener.class);
|
||||
StandardScaleGestureDetector detector = mock(StandardScaleGestureDetector.class);
|
||||
mapGestureDetector.addOnScaleListener(listener);
|
||||
mapGestureDetector.notifyOnScaleBeginListeners(detector);
|
||||
mapGestureDetector.notifyOnScaleListeners(detector);
|
||||
mapGestureDetector.notifyOnScaleEndListeners(detector);
|
||||
verify(listener, times(1)).onScaleBegin(detector);
|
||||
verify(listener, times(1)).onScale(detector);
|
||||
verify(listener, times(1)).onScaleEnd(detector);
|
||||
|
||||
mapGestureDetector.removeOnScaleListener(listener);
|
||||
mapGestureDetector.notifyOnScaleBeginListeners(detector);
|
||||
mapGestureDetector.notifyOnScaleListeners(detector);
|
||||
mapGestureDetector.notifyOnScaleEndListeners(detector);
|
||||
verify(listener, times(1)).onScaleBegin(detector);
|
||||
verify(listener, times(1)).onScale(detector);
|
||||
verify(listener, times(1)).onScaleEnd(detector);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onShoveListenerTest() throws Exception {
|
||||
MapboxMap.OnShoveListener listener = mock(MapboxMap.OnShoveListener.class);
|
||||
ShoveGestureDetector detector = mock(ShoveGestureDetector.class);
|
||||
mapGestureDetector.addShoveListener(listener);
|
||||
mapGestureDetector.notifyOnShoveBeginListeners(detector);
|
||||
mapGestureDetector.notifyOnShoveListeners(detector);
|
||||
mapGestureDetector.notifyOnShoveEndListeners(detector);
|
||||
verify(listener, times(1)).onShoveBegin(detector);
|
||||
verify(listener, times(1)).onShove(detector);
|
||||
verify(listener, times(1)).onShoveEnd(detector);
|
||||
|
||||
mapGestureDetector.removeShoveListener(listener);
|
||||
mapGestureDetector.notifyOnShoveBeginListeners(detector);
|
||||
mapGestureDetector.notifyOnShoveListeners(detector);
|
||||
mapGestureDetector.notifyOnShoveEndListeners(detector);
|
||||
verify(listener, times(1)).onShoveBegin(detector);
|
||||
verify(listener, times(1)).onShove(detector);
|
||||
verify(listener, times(1)).onShoveEnd(detector);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public class MapboxMapTest {
|
||||
mock(TrackingSettings.class),
|
||||
mock(MyLocationViewSettings.class),
|
||||
mock(Projection.class),
|
||||
mock(MapboxMap.OnRegisterTouchListener.class),
|
||||
mock(MapboxMap.OnGesturesManagerInteractionListener.class),
|
||||
mock(AnnotationManager.class),
|
||||
mock(CameraChangeDispatcher.class));
|
||||
}
|
||||
|
||||
@@ -8,24 +8,26 @@ ext {
|
||||
]
|
||||
|
||||
versions = [
|
||||
mapboxServices: '3.0.0-beta.2',
|
||||
mapboxServices : '3.0.0-beta.2',
|
||||
mapboxTelemetry: '3.0.0-beta.1',
|
||||
supportLib : '25.4.0',
|
||||
espresso : '3.0.1',
|
||||
testRunner : '1.0.1',
|
||||
leakCanary : '1.5.1',
|
||||
lost : '3.0.4',
|
||||
junit : '4.12',
|
||||
mockito : '2.10.0',
|
||||
robolectric : '3.5.1',
|
||||
timber : '4.5.1',
|
||||
okhttp : '3.9.1'
|
||||
mapboxGestures : '0.1.0-20180227.133736-12',
|
||||
supportLib : '25.4.0',
|
||||
espresso : '3.0.1',
|
||||
testRunner : '1.0.1',
|
||||
leakCanary : '1.5.1',
|
||||
lost : '3.0.4',
|
||||
junit : '4.12',
|
||||
mockito : '2.10.0',
|
||||
robolectric : '3.5.1',
|
||||
timber : '4.5.1',
|
||||
okhttp : '3.9.1'
|
||||
]
|
||||
|
||||
dependenciesList = [
|
||||
mapboxJavaServices : "com.mapbox.mapboxsdk:mapbox-sdk-services:${versions.mapboxServices}",
|
||||
mapboxJavaGeoJSON : "com.mapbox.mapboxsdk:mapbox-sdk-geojson:${versions.mapboxServices}",
|
||||
mapboxAndroidTelemetry: "com.mapbox.mapboxsdk:mapbox-android-telemetry:${versions.mapboxTelemetry}",
|
||||
mapboxAndroidGestures : "com.mapbox.mapboxsdk:mapbox-android-gestures:${versions.mapboxGestures}@aar",
|
||||
|
||||
// for testApp
|
||||
mapboxJavaTurf : "com.mapbox.mapboxsdk:mapbox-sdk-turf:${versions.mapboxServices}",
|
||||
|
||||
Reference in New Issue
Block a user