From c3068ec3975c0c13486c5a456cc9ae26baf4f755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Mon, 15 Jan 2018 13:47:06 +0100 Subject: Camera callbacks for velocity animated movements (#10925) * [android] camera listeners double invocation fix * [android] invoking camera change callbacks for velocity animated movements --- .../mapboxsdk/maps/CameraChangeDispatcher.java | 19 ++++---- .../mapbox/mapboxsdk/maps/MapGestureDetector.java | 50 +++++++++++++++++----- .../java/com/mapbox/mapboxsdk/maps/Transform.java | 12 +++--- 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java index 605c8912e2..e558a5d707 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java @@ -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,10 +131,6 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M @Override public void onCameraMoveStarted(final int reason) { - if (!idle) { - return; - } - idle = false; moveStartedReason = reason; handler.post(onCameraMoveStartedRunnable); } @@ -141,10 +147,7 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M @Override public void onCameraIdle() { - if (!idle) { - idle = true; - handler.post(onCameraIdleRunnable); - } + handler.post(onCameraIdleRunnable); } void addOnCameraIdleListener(@NonNull OnCameraIdleListener listener) { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java index 214fa22795..1788cb4428 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java @@ -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(); } }); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java index b0cc92c62b..7fa85ae550 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java @@ -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); } } -- cgit v1.2.1