[android ] - new gestures library (#11221)
* [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
This commit is contained in:
@@ -3,6 +3,7 @@ apply plugin: 'com.android.library'
|
|||||||
dependencies {
|
dependencies {
|
||||||
api dependenciesList.mapboxAndroidTelemetry
|
api dependenciesList.mapboxAndroidTelemetry
|
||||||
api dependenciesList.mapboxJavaGeoJSON
|
api dependenciesList.mapboxJavaGeoJSON
|
||||||
|
api dependenciesList.mapboxAndroidGestures
|
||||||
implementation dependenciesList.supportAnnotations
|
implementation dependenciesList.supportAnnotations
|
||||||
implementation dependenciesList.supportFragmentV4
|
implementation dependenciesList.supportFragmentV4
|
||||||
implementation dependenciesList.timber
|
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;
|
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.
|
* The currently supported minimum zoom level.
|
||||||
*/
|
*/
|
||||||
@@ -78,14 +103,14 @@ public class MapboxConstants {
|
|||||||
public static final double MINIMUM_DIRECTION = 0;
|
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;
|
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
|
* 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
|
* Fragment Argument Key for MapboxMapOptions
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -128,7 +128,7 @@ final class MapKeyListener {
|
|||||||
|
|
||||||
// Zoom out
|
// Zoom out
|
||||||
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
||||||
transform.zoom(false, focalPoint);
|
transform.zoomOut(focalPoint);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -164,7 +164,7 @@ final class MapKeyListener {
|
|||||||
|
|
||||||
// Zoom in
|
// Zoom in
|
||||||
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
||||||
transform.zoom(true, focalPoint);
|
transform.zoomIn(focalPoint);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ final class MapKeyListener {
|
|||||||
if (currentTrackballLongPressTimeOut != null) {
|
if (currentTrackballLongPressTimeOut != null) {
|
||||||
// Zoom in
|
// Zoom in
|
||||||
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
||||||
transform.zoom(true, focalPoint);
|
transform.zoomIn(focalPoint);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ final class MapKeyListener {
|
|||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
// Zoom out
|
// Zoom out
|
||||||
PointF pointF = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
PointF pointF = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
|
||||||
transform.zoom(false, pointF);
|
transform.zoomOut(pointF);
|
||||||
|
|
||||||
// Ensure the up action is not run
|
// Ensure the up action is not run
|
||||||
currentTrackballLongPressTimeOut = null;
|
currentTrackballLongPressTimeOut = null;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.widget.FrameLayout;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ZoomButtonsController;
|
import android.widget.ZoomButtonsController;
|
||||||
|
|
||||||
|
import com.mapbox.android.gestures.AndroidGesturesManager;
|
||||||
import com.mapbox.android.telemetry.AppUserTurnstile;
|
import com.mapbox.android.telemetry.AppUserTurnstile;
|
||||||
import com.mapbox.android.telemetry.Event;
|
import com.mapbox.android.telemetry.Event;
|
||||||
import com.mapbox.android.telemetry.MapEventFactory;
|
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.net.ConnectivityReceiver;
|
||||||
import com.mapbox.mapboxsdk.storage.FileSource;
|
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.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@@ -52,6 +51,9 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
|
import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
|
||||||
@@ -149,7 +151,7 @@ public class MapView extends FrameLayout {
|
|||||||
focalPointInvalidator.addListener(createFocalPointChangeListener());
|
focalPointInvalidator.addListener(createFocalPointChangeListener());
|
||||||
|
|
||||||
// callback for registering touch listeners
|
// callback for registering touch listeners
|
||||||
RegisterTouchListener registerTouchListener = new RegisterTouchListener();
|
GesturesManagerInteractionListener registerTouchListener = new GesturesManagerInteractionListener();
|
||||||
|
|
||||||
// callback for zooming in the camera
|
// callback for zooming in the camera
|
||||||
CameraZoomInvalidator zoomInvalidator = new CameraZoomInvalidator();
|
CameraZoomInvalidator zoomInvalidator = new CameraZoomInvalidator();
|
||||||
@@ -184,7 +186,7 @@ public class MapView extends FrameLayout {
|
|||||||
mapCallback.attachMapboxMap(mapboxMap);
|
mapCallback.attachMapboxMap(mapboxMap);
|
||||||
|
|
||||||
// user input
|
// user input
|
||||||
mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings,
|
mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings,
|
||||||
annotationManager, cameraChangeDispatcher);
|
annotationManager, cameraChangeDispatcher);
|
||||||
mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings);
|
mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings);
|
||||||
|
|
||||||
@@ -388,6 +390,7 @@ public class MapView extends FrameLayout {
|
|||||||
public void onStop() {
|
public void onStop() {
|
||||||
if (mapboxMap != null) {
|
if (mapboxMap != null) {
|
||||||
// map was destroyed before it was started
|
// map was destroyed before it was started
|
||||||
|
mapGestureDetector.cancelAnimators();
|
||||||
mapboxMap.onStop();
|
mapboxMap.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,7 +924,7 @@ public class MapView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RegisterTouchListener implements MapboxMap.OnRegisterTouchListener {
|
private class GesturesManagerInteractionListener implements MapboxMap.OnGesturesManagerInteractionListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSetMapClickListener(MapboxMap.OnMapClickListener listener) {
|
public void onSetMapClickListener(MapboxMap.OnMapClickListener listener) {
|
||||||
@@ -982,6 +985,56 @@ public class MapView extends FrameLayout {
|
|||||||
public void onRemoveFlingListener(MapboxMap.OnFlingListener listener) {
|
public void onRemoveFlingListener(MapboxMap.OnFlingListener listener) {
|
||||||
mapGestureDetector.removeOnFlingListener(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 {
|
private static class MapZoomControllerListener implements ZoomButtonsController.OnZoomListener {
|
||||||
@@ -1019,11 +1072,13 @@ public class MapView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onZoom(boolean zoomIn, @Nullable PointF focalPoint) {
|
private void onZoom(boolean zoomIn, @Nullable PointF focalPoint) {
|
||||||
if (focalPoint != null) {
|
if (focalPoint == null) {
|
||||||
transform.zoom(zoomIn, focalPoint);
|
focalPoint = new PointF(mapWidth / 2, mapHeight / 2);
|
||||||
|
}
|
||||||
|
if (zoomIn) {
|
||||||
|
transform.zoomIn(focalPoint);
|
||||||
} else {
|
} else {
|
||||||
PointF centerPoint = new PointF(mapWidth / 2, mapHeight / 2);
|
transform.zoomOut(focalPoint);
|
||||||
transform.zoom(zoomIn, centerPoint);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ import android.text.TextUtils;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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.Feature;
|
||||||
import com.mapbox.geojson.Geometry;
|
import com.mapbox.geojson.Geometry;
|
||||||
import com.mapbox.mapboxsdk.annotations.Annotation;
|
import com.mapbox.mapboxsdk.annotations.Annotation;
|
||||||
@@ -43,7 +49,6 @@ import com.mapbox.mapboxsdk.style.layers.Filter;
|
|||||||
import com.mapbox.mapboxsdk.style.layers.Layer;
|
import com.mapbox.mapboxsdk.style.layers.Layer;
|
||||||
import com.mapbox.mapboxsdk.style.light.Light;
|
import com.mapbox.mapboxsdk.style.light.Light;
|
||||||
import com.mapbox.mapboxsdk.style.sources.Source;
|
import com.mapbox.mapboxsdk.style.sources.Source;
|
||||||
import com.mapbox.android.core.location.LocationEngine;
|
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -73,13 +78,13 @@ public final class MapboxMap {
|
|||||||
private final MyLocationViewSettings myLocationViewSettings;
|
private final MyLocationViewSettings myLocationViewSettings;
|
||||||
private final CameraChangeDispatcher cameraChangeDispatcher;
|
private final CameraChangeDispatcher cameraChangeDispatcher;
|
||||||
|
|
||||||
private final OnRegisterTouchListener onRegisterTouchListener;
|
private final OnGesturesManagerInteractionListener onGesturesManagerInteractionListener;
|
||||||
|
|
||||||
private MapboxMap.OnFpsChangedListener onFpsChangedListener;
|
private MapboxMap.OnFpsChangedListener onFpsChangedListener;
|
||||||
private PointF focalPoint;
|
private PointF focalPoint;
|
||||||
|
|
||||||
MapboxMap(NativeMapView map, Transform transform, UiSettings ui, TrackingSettings tracking,
|
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) {
|
AnnotationManager annotations, CameraChangeDispatcher cameraChangeDispatcher) {
|
||||||
this.nativeMapView = map;
|
this.nativeMapView = map;
|
||||||
this.uiSettings = ui;
|
this.uiSettings = ui;
|
||||||
@@ -88,7 +93,7 @@ public final class MapboxMap {
|
|||||||
this.myLocationViewSettings = myLocationView;
|
this.myLocationViewSettings = myLocationView;
|
||||||
this.annotationManager = annotations.bind(this);
|
this.annotationManager = annotations.bind(this);
|
||||||
this.transform = transform;
|
this.transform = transform;
|
||||||
this.onRegisterTouchListener = listener;
|
this.onGesturesManagerInteractionListener = listener;
|
||||||
this.cameraChangeDispatcher = cameraChangeDispatcher;
|
this.cameraChangeDispatcher = cameraChangeDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1882,12 +1887,11 @@ public final class MapboxMap {
|
|||||||
*
|
*
|
||||||
* @param listener The callback that's invoked when the map is scrolled.
|
* @param listener The callback that's invoked when the map is scrolled.
|
||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*
|
|
||||||
* @deprecated Use {@link #addOnScrollListener(OnScrollListener)} instead.
|
* @deprecated Use {@link #addOnScrollListener(OnScrollListener)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setOnScrollListener(@Nullable OnScrollListener listener) {
|
public void setOnScrollListener(@Nullable OnScrollListener listener) {
|
||||||
onRegisterTouchListener.onSetScrollListener(listener);
|
onGesturesManagerInteractionListener.onSetScrollListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1895,10 +1899,9 @@ public final class MapboxMap {
|
|||||||
*
|
*
|
||||||
* @param listener The callback that's invoked when the map is scrolled.
|
* @param listener The callback that's invoked when the map is scrolled.
|
||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void addOnScrollListener(@Nullable OnScrollListener listener) {
|
public void addOnScrollListener(@Nullable OnScrollListener listener) {
|
||||||
onRegisterTouchListener.onAddScrollListener(listener);
|
onGesturesManagerInteractionListener.onAddScrollListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1906,10 +1909,9 @@ public final class MapboxMap {
|
|||||||
*
|
*
|
||||||
* @param listener The callback that's invoked when the map is scrolled.
|
* @param listener The callback that's invoked when the map is scrolled.
|
||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void removeOnScrollListener(@Nullable OnScrollListener listener) {
|
public void removeOnScrollListener(@Nullable OnScrollListener listener) {
|
||||||
onRegisterTouchListener.onRemoveScrollListener(listener);
|
onGesturesManagerInteractionListener.onRemoveScrollListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1917,12 +1919,11 @@ public final class MapboxMap {
|
|||||||
*
|
*
|
||||||
* @param listener The callback that's invoked when the map is flinged.
|
* @param listener The callback that's invoked when the map is flinged.
|
||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*
|
|
||||||
* @deprecated Use {@link #addOnFlingListener(OnFlingListener)} instead.
|
* @deprecated Use {@link #addOnFlingListener(OnFlingListener)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setOnFlingListener(@Nullable OnFlingListener listener) {
|
public void setOnFlingListener(@Nullable OnFlingListener listener) {
|
||||||
onRegisterTouchListener.onSetFlingListener(listener);
|
onGesturesManagerInteractionListener.onSetFlingListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1932,7 +1933,7 @@ public final class MapboxMap {
|
|||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*/
|
*/
|
||||||
public void addOnFlingListener(@Nullable OnFlingListener listener) {
|
public void addOnFlingListener(@Nullable OnFlingListener listener) {
|
||||||
onRegisterTouchListener.onAddFlingListener(listener);
|
onGesturesManagerInteractionListener.onAddFlingListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1942,7 +1943,98 @@ public final class MapboxMap {
|
|||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*/
|
*/
|
||||||
public void removeOnFlingListener(@Nullable OnFlingListener listener) {
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1950,12 +2042,11 @@ public final class MapboxMap {
|
|||||||
*
|
*
|
||||||
* @param listener The callback that's invoked when the user clicks on the map view.
|
* @param listener The callback that's invoked when the user clicks on the map view.
|
||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*
|
|
||||||
* @deprecated Use {@link #addOnMapClickListener(OnMapClickListener)} instead.
|
* @deprecated Use {@link #addOnMapClickListener(OnMapClickListener)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setOnMapClickListener(@Nullable OnMapClickListener listener) {
|
public void setOnMapClickListener(@Nullable OnMapClickListener listener) {
|
||||||
onRegisterTouchListener.onSetMapClickListener(listener);
|
onGesturesManagerInteractionListener.onSetMapClickListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1965,7 +2056,7 @@ public final class MapboxMap {
|
|||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*/
|
*/
|
||||||
public void addOnMapClickListener(@Nullable OnMapClickListener listener) {
|
public void addOnMapClickListener(@Nullable OnMapClickListener listener) {
|
||||||
onRegisterTouchListener.onAddMapClickListener(listener);
|
onGesturesManagerInteractionListener.onAddMapClickListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1975,7 +2066,7 @@ public final class MapboxMap {
|
|||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*/
|
*/
|
||||||
public void removeOnMapClickListener(@Nullable OnMapClickListener listener) {
|
public void removeOnMapClickListener(@Nullable OnMapClickListener listener) {
|
||||||
onRegisterTouchListener.onRemoveMapClickListener(listener);
|
onGesturesManagerInteractionListener.onRemoveMapClickListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1983,12 +2074,11 @@ public final class MapboxMap {
|
|||||||
*
|
*
|
||||||
* @param listener The callback that's invoked when the user long clicks on the map view.
|
* @param listener The callback that's invoked when the user long clicks on the map view.
|
||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*
|
|
||||||
* @deprecated Use {@link #addOnMapLongClickListener(OnMapLongClickListener)} instead.
|
* @deprecated Use {@link #addOnMapLongClickListener(OnMapLongClickListener)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
|
public void setOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
|
||||||
onRegisterTouchListener.onSetMapLongClickListener(listener);
|
onGesturesManagerInteractionListener.onSetMapLongClickListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1998,7 +2088,7 @@ public final class MapboxMap {
|
|||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*/
|
*/
|
||||||
public void addOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
|
public void addOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
|
||||||
onRegisterTouchListener.onAddMapLongClickListener(listener);
|
onGesturesManagerInteractionListener.onAddMapLongClickListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2008,7 +2098,7 @@ public final class MapboxMap {
|
|||||||
* To unset the callback, use null.
|
* To unset the callback, use null.
|
||||||
*/
|
*/
|
||||||
public void removeOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
|
public void removeOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
|
||||||
onRegisterTouchListener.onRemoveMapLongClickListener(listener);
|
onGesturesManagerInteractionListener.onRemoveMapLongClickListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2267,7 +2357,9 @@ public final class MapboxMap {
|
|||||||
* Interface definition for a callback to be invoked when the map is scrolled.
|
* Interface definition for a callback to be invoked when the map is scrolled.
|
||||||
*
|
*
|
||||||
* @see MapboxMap#setOnScrollListener(OnScrollListener)
|
* @see MapboxMap#setOnScrollListener(OnScrollListener)
|
||||||
|
* @deprecated Use {@link OnMoveListener} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public interface OnScrollListener {
|
public interface OnScrollListener {
|
||||||
/**
|
/**
|
||||||
* Called when the map is scrolled.
|
* Called when the map is scrolled.
|
||||||
@@ -2275,6 +2367,58 @@ public final class MapboxMap {
|
|||||||
void onScroll();
|
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.
|
* Interface definition for a callback to be invoked when the camera changes position.
|
||||||
*
|
*
|
||||||
@@ -2377,7 +2521,7 @@ public final class MapboxMap {
|
|||||||
* Interface definition for a callback to be invoked when a user registers an listener that is
|
* Interface definition for a callback to be invoked when a user registers an listener that is
|
||||||
* related to touch and click events.
|
* related to touch and click events.
|
||||||
*/
|
*/
|
||||||
interface OnRegisterTouchListener {
|
interface OnGesturesManagerInteractionListener {
|
||||||
void onSetMapClickListener(OnMapClickListener listener);
|
void onSetMapClickListener(OnMapClickListener listener);
|
||||||
|
|
||||||
void onAddMapClickListener(OnMapClickListener listener);
|
void onAddMapClickListener(OnMapClickListener listener);
|
||||||
@@ -2401,6 +2545,26 @@ public final class MapboxMap {
|
|||||||
void onAddFlingListener(OnFlingListener listener);
|
void onAddFlingListener(OnFlingListener listener);
|
||||||
|
|
||||||
void onRemoveFlingListener(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
|
// cancel ongoing transitions
|
||||||
mapView.cancelTransitions();
|
mapView.cancelTransitions();
|
||||||
|
|
||||||
|
cameraChangeDispatcher.onCameraIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@@ -235,39 +237,37 @@ final class Transform implements MapView.OnMapChangedListener {
|
|||||||
return mapView.getZoom();
|
return mapView.getZoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
void zoom(boolean zoomIn, @NonNull PointF focalPoint) {
|
void zoomIn(@NonNull PointF focalPoint) {
|
||||||
CameraPosition cameraPosition = invalidateCameraPosition();
|
CameraPosition cameraPosition = invalidateCameraPosition();
|
||||||
if (cameraPosition != null) {
|
if (cameraPosition != null) {
|
||||||
int newZoom = (int) Math.round(cameraPosition.zoom + (zoomIn ? 1 : -1));
|
int newZoom = (int) Math.round(cameraPosition.zoom + 1);
|
||||||
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION, false);
|
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION);
|
||||||
} else {
|
|
||||||
// we are not transforming, notify about being idle
|
|
||||||
cameraChangeDispatcher.onCameraIdle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void zoom(double zoomAddition, @NonNull PointF focalPoint, long duration) {
|
void zoomOut(@NonNull PointF focalPoint) {
|
||||||
CameraPosition cameraPosition = invalidateCameraPosition();
|
CameraPosition cameraPosition = invalidateCameraPosition();
|
||||||
if (cameraPosition != null) {
|
if (cameraPosition != null) {
|
||||||
int newZoom = (int) Math.round(cameraPosition.zoom + zoomAddition);
|
int newZoom = (int) Math.round(cameraPosition.zoom - 1);
|
||||||
setZoom(newZoom, focalPoint, duration, false);
|
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION);
|
||||||
} else {
|
|
||||||
// we are not transforming, notify about being idle
|
|
||||||
cameraChangeDispatcher.onCameraIdle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void zoomBy(double zoomAddition, @NonNull PointF focalPoint) {
|
||||||
|
setZoom(mapView.getZoom() + zoomAddition, focalPoint, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void setZoom(double zoom, @NonNull PointF focalPoint) {
|
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) {
|
if (mapView != null) {
|
||||||
mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
|
mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onMapChanged(int change) {
|
public void onMapChanged(int change) {
|
||||||
if (change == MapView.REGION_DID_CHANGE_ANIMATED) {
|
if (change == MapView.REGION_DID_CHANGE_ANIMATED) {
|
||||||
if (!isAnimator) {
|
if (duration > 0) {
|
||||||
cameraChangeDispatcher.onCameraIdle();
|
cameraChangeDispatcher.onCameraIdle();
|
||||||
}
|
}
|
||||||
mapView.removeOnMapChangedListener(this);
|
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) {
|
void moveBy(double offsetX, double offsetY, long duration) {
|
||||||
if (duration > 0) {
|
if (duration > 0) {
|
||||||
mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
|
mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
|
||||||
|
|||||||
@@ -6,4 +6,13 @@
|
|||||||
<dimen name="mapbox_eight_dp">8dp</dimen>
|
<dimen name="mapbox_eight_dp">8dp</dimen>
|
||||||
<dimen name="mapbox_ninety_two_dp">92dp</dimen>
|
<dimen name="mapbox_ninety_two_dp">92dp</dimen>
|
||||||
<dimen name="mapbox_my_locationview_outer_circle">18dp</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>
|
</resources>
|
||||||
|
|||||||
@@ -2,8 +2,13 @@ package com.mapbox.mapboxsdk.maps;
|
|||||||
|
|
||||||
import android.graphics.PointF;
|
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 com.mapbox.mapboxsdk.geometry.LatLng;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@@ -13,16 +18,23 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
public class MapTouchListenersTest {
|
public class MapTouchListenersTest {
|
||||||
|
|
||||||
@Test
|
private MapGestureDetector mapGestureDetector;
|
||||||
public void onMapClickListenerTest() throws Exception {
|
private LatLng latLng;
|
||||||
LatLng latLng = new LatLng();
|
private PointF pointF;
|
||||||
PointF pointF = new PointF();
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
latLng = new LatLng();
|
||||||
|
pointF = new PointF();
|
||||||
|
|
||||||
Projection projection = mock(Projection.class);
|
Projection projection = mock(Projection.class);
|
||||||
when(projection.fromScreenLocation(pointF)).thenReturn(latLng);
|
when(projection.fromScreenLocation(pointF)).thenReturn(latLng);
|
||||||
MapGestureDetector mapGestureDetector = new MapGestureDetector(null,
|
mapGestureDetector = new MapGestureDetector(null,
|
||||||
null, projection, null, null, null, null);
|
null, projection, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onMapClickListenerTest() throws Exception {
|
||||||
MapboxMap.OnMapClickListener listener = mock(MapboxMap.OnMapClickListener.class);
|
MapboxMap.OnMapClickListener listener = mock(MapboxMap.OnMapClickListener.class);
|
||||||
mapGestureDetector.addOnMapClickListener(listener);
|
mapGestureDetector.addOnMapClickListener(listener);
|
||||||
mapGestureDetector.notifyOnMapClickListeners(pointF);
|
mapGestureDetector.notifyOnMapClickListeners(pointF);
|
||||||
@@ -35,14 +47,6 @@ public class MapTouchListenersTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onMapLongClickListenerTest() throws Exception {
|
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);
|
MapboxMap.OnMapLongClickListener listener = mock(MapboxMap.OnMapLongClickListener.class);
|
||||||
mapGestureDetector.addOnMapLongClickListener(listener);
|
mapGestureDetector.addOnMapLongClickListener(listener);
|
||||||
mapGestureDetector.notifyOnMapLongClickListeners(pointF);
|
mapGestureDetector.notifyOnMapLongClickListeners(pointF);
|
||||||
@@ -55,14 +59,6 @@ public class MapTouchListenersTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onFlingListenerTest() throws Exception {
|
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);
|
MapboxMap.OnFlingListener listener = mock(MapboxMap.OnFlingListener.class);
|
||||||
mapGestureDetector.addOnFlingListener(listener);
|
mapGestureDetector.addOnFlingListener(listener);
|
||||||
mapGestureDetector.notifyOnFlingListeners();
|
mapGestureDetector.notifyOnFlingListeners();
|
||||||
@@ -75,14 +71,6 @@ public class MapTouchListenersTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onScrollListenerTest() throws Exception {
|
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);
|
MapboxMap.OnScrollListener listener = mock(MapboxMap.OnScrollListener.class);
|
||||||
mapGestureDetector.addOnScrollListener(listener);
|
mapGestureDetector.addOnScrollListener(listener);
|
||||||
mapGestureDetector.notifyOnScrollListeners();
|
mapGestureDetector.notifyOnScrollListeners();
|
||||||
@@ -92,4 +80,88 @@ public class MapTouchListenersTest {
|
|||||||
mapGestureDetector.notifyOnScrollListeners();
|
mapGestureDetector.notifyOnScrollListeners();
|
||||||
verify(listener, times(1)).onScroll();
|
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(TrackingSettings.class),
|
||||||
mock(MyLocationViewSettings.class),
|
mock(MyLocationViewSettings.class),
|
||||||
mock(Projection.class),
|
mock(Projection.class),
|
||||||
mock(MapboxMap.OnRegisterTouchListener.class),
|
mock(MapboxMap.OnGesturesManagerInteractionListener.class),
|
||||||
mock(AnnotationManager.class),
|
mock(AnnotationManager.class),
|
||||||
mock(CameraChangeDispatcher.class));
|
mock(CameraChangeDispatcher.class));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,24 +8,26 @@ ext {
|
|||||||
]
|
]
|
||||||
|
|
||||||
versions = [
|
versions = [
|
||||||
mapboxServices: '3.0.0-beta.2',
|
mapboxServices : '3.0.0-beta.2',
|
||||||
mapboxTelemetry: '3.0.0-beta.1',
|
mapboxTelemetry: '3.0.0-beta.1',
|
||||||
supportLib : '25.4.0',
|
mapboxGestures : '0.1.0-20180227.133736-12',
|
||||||
espresso : '3.0.1',
|
supportLib : '25.4.0',
|
||||||
testRunner : '1.0.1',
|
espresso : '3.0.1',
|
||||||
leakCanary : '1.5.1',
|
testRunner : '1.0.1',
|
||||||
lost : '3.0.4',
|
leakCanary : '1.5.1',
|
||||||
junit : '4.12',
|
lost : '3.0.4',
|
||||||
mockito : '2.10.0',
|
junit : '4.12',
|
||||||
robolectric : '3.5.1',
|
mockito : '2.10.0',
|
||||||
timber : '4.5.1',
|
robolectric : '3.5.1',
|
||||||
okhttp : '3.9.1'
|
timber : '4.5.1',
|
||||||
|
okhttp : '3.9.1'
|
||||||
]
|
]
|
||||||
|
|
||||||
dependenciesList = [
|
dependenciesList = [
|
||||||
mapboxJavaServices : "com.mapbox.mapboxsdk:mapbox-sdk-services:${versions.mapboxServices}",
|
mapboxJavaServices : "com.mapbox.mapboxsdk:mapbox-sdk-services:${versions.mapboxServices}",
|
||||||
mapboxJavaGeoJSON : "com.mapbox.mapboxsdk:mapbox-sdk-geojson:${versions.mapboxServices}",
|
mapboxJavaGeoJSON : "com.mapbox.mapboxsdk:mapbox-sdk-geojson:${versions.mapboxServices}",
|
||||||
mapboxAndroidTelemetry: "com.mapbox.mapboxsdk:mapbox-android-telemetry:${versions.mapboxTelemetry}",
|
mapboxAndroidTelemetry: "com.mapbox.mapboxsdk:mapbox-android-telemetry:${versions.mapboxTelemetry}",
|
||||||
|
mapboxAndroidGestures : "com.mapbox.mapboxsdk:mapbox-android-gestures:${versions.mapboxGestures}@aar",
|
||||||
|
|
||||||
// for testApp
|
// for testApp
|
||||||
mapboxJavaTurf : "com.mapbox.mapboxsdk:mapbox-sdk-turf:${versions.mapboxServices}",
|
mapboxJavaTurf : "com.mapbox.mapboxsdk:mapbox-sdk-turf:${versions.mapboxServices}",
|
||||||
|
|||||||
Reference in New Issue
Block a user