Camera callbacks for velocity animated movements (#10925)

* [android] camera listeners double invocation fix

* [android] invoking camera change callbacks for velocity animated movements
This commit is contained in:
Łukasz Paczos
2018-01-15 13:47:06 +01:00
committed by GitHub
parent b2aa8d6ca5
commit 5782b6be48
3 changed files with 57 additions and 61 deletions

View File

@@ -34,6 +34,11 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M
private final Runnable onCameraMoveStartedRunnable = new Runnable() {
@Override
public void run() {
if (!idle) {
return;
}
idle = false;
// deprecated API
if (onCameraMoveStartedListener != null) {
onCameraMoveStartedListener.onCameraMoveStarted(moveStartedReason);
@@ -85,6 +90,11 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M
private final Runnable onCameraIdleRunnable = new Runnable() {
@Override
public void run() {
if (idle) {
return;
}
idle = true;
// deprecated API
if (onCameraIdleListener != null) {
onCameraIdleListener.onCameraIdle();
@@ -121,67 +131,23 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M
@Override
public void onCameraMoveStarted(final int reason) {
if (!idle) {
return;
}
idle = false;
moveStartedReason = reason;
handler.post(onCameraMoveStartedRunnable);
// new API
if (!onCameraMoveStarted.isEmpty()) {
for (OnCameraMoveStartedListener cameraMoveStartedListener : onCameraMoveStarted) {
cameraMoveStartedListener.onCameraMoveStarted(reason);
}
}
}
@Override
public void onCameraMove() {
handler.post(onCameraMoveRunnable);
if (onCameraMoveListener != null && !idle) {
onCameraMoveListener.onCameraMove();
}
// new API
if (!onCameraMove.isEmpty() && !idle) {
for (OnCameraMoveListener cameraMoveListener : onCameraMove) {
cameraMoveListener.onCameraMove();
}
}
}
@Override
public void onCameraMoveCanceled() {
handler.post(onCameraMoveCancelRunnable);
if (onCameraMoveCanceledListener != null && !idle) {
onCameraMoveCanceledListener.onCameraMoveCanceled();
}
// new API
if (!onCameraMoveCanceled.isEmpty() && !idle) {
for (OnCameraMoveCanceledListener cameraMoveCanceledListener : onCameraMoveCanceled) {
cameraMoveCanceledListener.onCameraMoveCanceled();
}
}
}
@Override
public void onCameraIdle() {
if (!idle) {
idle = true;
handler.post(onCameraIdleRunnable);
if (onCameraIdleListener != null) {
onCameraIdleListener.onCameraIdle();
}
// new API
if (!onCameraIdle.isEmpty()) {
for (OnCameraIdleListener cameraIdleListener : onCameraIdle) {
cameraIdleListener.onCameraIdle();
}
}
}
handler.post(onCameraIdleRunnable);
}
void addOnCameraIdleListener(@NonNull OnCameraIdleListener listener) {

View File

@@ -28,6 +28,7 @@ import com.mapbox.services.android.telemetry.utils.TelemetryUtils;
import java.util.concurrent.CopyOnWriteArrayList;
import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener.REASON_API_ANIMATION;
import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE;
/**
@@ -78,9 +79,11 @@ final class MapGestureDetector {
private boolean scaleGestureOccurred;
private boolean recentScaleGestureOccurred;
private boolean scaleAnimating;
private long scaleBeginTime;
private boolean scaleAnimating;
private boolean rotateAnimating;
private VelocityTracker velocityTracker;
private boolean wasZoomingIn;
private boolean wasClockwiseRotating;
@@ -233,7 +236,10 @@ final class MapGestureDetector {
MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapDragEndEvent(
getLocationFromGesture(event.getX(), event.getY()), transform));
scrollGestureOccurred = false;
cameraChangeDispatcher.onCameraIdle();
if (!scaleAnimating && !rotateAnimating) {
cameraChangeDispatcher.onCameraIdle();
}
}
twoTap = false;
@@ -615,7 +621,6 @@ final class MapGestureDetector {
return;
}
if (rotateGestureOccurred || quickZoom) {
reset();
return;
@@ -657,13 +662,23 @@ final class MapGestureDetector {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
transform.setZoom((Float) animation.getAnimatedValue(), scalePointBegin);
transform.setZoom((Float) animation.getAnimatedValue(), scalePointBegin, 0, true);
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_ANIMATION);
}
@Override
public void onAnimationCancel(Animator animation) {
reset();
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
reset();
}
});
@@ -682,7 +697,6 @@ final class MapGestureDetector {
private long beginTime = 0;
private boolean started = false;
private boolean animating = false;
// Called when two fingers first touch the screen
@Override
@@ -753,9 +767,9 @@ final class MapGestureDetector {
}
double angularVelocity = calculateVelocityVector(detector);
if (Math.abs(angularVelocity) > 0.001 && rotateGestureOccurred && !animating) {
if (Math.abs(angularVelocity) > 0.001 && rotateGestureOccurred && !rotateAnimating) {
animateRotateVelocity();
} else if (!animating) {
} else if (!rotateAnimating) {
reset();
}
}
@@ -763,12 +777,16 @@ final class MapGestureDetector {
private void reset() {
beginTime = 0;
started = false;
animating = false;
rotateAnimating = false;
rotateGestureOccurred = false;
if (!twoTap) {
cameraChangeDispatcher.onCameraIdle();
}
}
private void animateRotateVelocity() {
animating = true;
rotateAnimating = true;
double currentRotation = transform.getRawBearing();
double rotateAdditionDegrees = calculateVelocityInDegrees();
createAnimator(currentRotation, rotateAdditionDegrees).start();
@@ -811,9 +829,19 @@ final class MapGestureDetector {
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_ANIMATION);
}
@Override
public void onAnimationCancel(Animator animation) {
reset();
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
reset();
}
});

View File

@@ -239,7 +239,7 @@ final class Transform implements MapView.OnMapChangedListener {
CameraPosition cameraPosition = invalidateCameraPosition();
if (cameraPosition != null) {
int newZoom = (int) Math.round(cameraPosition.zoom + (zoomIn ? 1 : -1));
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION);
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION, false);
} else {
// we are not transforming, notify about being idle
cameraChangeDispatcher.onCameraIdle();
@@ -250,7 +250,7 @@ final class Transform implements MapView.OnMapChangedListener {
CameraPosition cameraPosition = invalidateCameraPosition();
if (cameraPosition != null) {
int newZoom = (int) Math.round(cameraPosition.zoom + zoomAddition);
setZoom(newZoom, focalPoint, duration);
setZoom(newZoom, focalPoint, duration, false);
} else {
// we are not transforming, notify about being idle
cameraChangeDispatcher.onCameraIdle();
@@ -258,16 +258,18 @@ final class Transform implements MapView.OnMapChangedListener {
}
void setZoom(double zoom, @NonNull PointF focalPoint) {
setZoom(zoom, focalPoint, 0);
setZoom(zoom, focalPoint, 0, false);
}
void setZoom(double zoom, @NonNull PointF focalPoint, long duration) {
void setZoom(double zoom, @NonNull PointF focalPoint, long duration, boolean isAnimator) {
if (mapView != null) {
mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
@Override
public void onMapChanged(int change) {
if (change == MapView.REGION_DID_CHANGE_ANIMATED) {
cameraChangeDispatcher.onCameraIdle();
if (!isAnimator) {
cameraChangeDispatcher.onCameraIdle();
}
mapView.removeOnMapChangedListener(this);
}
}