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 5f5a10d0d07..17ade7b5fac 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 @@ -218,15 +218,17 @@ boolean onTouchEvent(MotionEvent motionEvent) { } void cancelAnimators() { - if (scaleAnimator != null) { - scaleAnimator.cancel(); - } - if (rotateAnimator != null) { - rotateAnimator.cancel(); - } - animationsTimeoutHandler.removeCallbacksAndMessages(null); scheduledAnimators.clear(); + + cancelAnimator(scaleAnimator); + cancelAnimator(rotateAnimator); + } + + private void cancelAnimator(Animator animator) { + if (animator != null && animator.isStarted()) { + animator.cancel(); + } } /** @@ -338,15 +340,18 @@ public boolean onDoubleTapEvent(MotionEvent motionEvent) { transform.cancelTransitions(); cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); + PointF zoomFocalPoint; // Single finger double tap if (focalPoint != null) { // User provided focal point - transform.zoomIn(focalPoint); + zoomFocalPoint = focalPoint; } else { // Zoom in on gesture - transform.zoomIn(new PointF(motionEvent.getX(), motionEvent.getY())); + zoomFocalPoint = new PointF(motionEvent.getX(), motionEvent.getY()); } + zoomInAnimated(zoomFocalPoint, false); + sendTelemetryEvent(Events.DOUBLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY())); return true; @@ -512,7 +517,7 @@ public void onScaleEnd(StandardScaleGestureDetector detector, float velocityX, f double zoomAddition = calculateScale(velocityXY, detector.isScalingOut()); double currentZoom = transform.getRawZoom(); long animationTime = (long) (Math.abs(zoomAddition) * 1000 / 4); - scaleAnimator = createScaleAnimator(currentZoom, zoomAddition, animationTime); + scaleAnimator = createScaleAnimator(currentZoom, zoomAddition, scaleFocalPoint, animationTime); scheduleAnimator(scaleAnimator); } @@ -540,39 +545,6 @@ private double calculateScale(double velocityXY, boolean isScalingOut) { return zoomAddition; } - private Animator createScaleAnimator(double currentZoom, double zoomAddition, long animationTime) { - ValueAnimator animator = ValueAnimator.ofFloat((float) currentZoom, (float) (currentZoom + zoomAddition)); - animator.setDuration(animationTime); - animator.setInterpolator(new DecelerateInterpolator()); - animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - - @Override - public void onAnimationUpdate(ValueAnimator animation) { - transform.setZoom((Float) animation.getAnimatedValue(), scaleFocalPoint, 0); - } - }); - - animator.addListener(new AnimatorListenerAdapter() { - - @Override - public void onAnimationStart(Animator animation) { - transform.cancelTransitions(); - cameraChangeDispatcher.onCameraMoveStarted(REASON_API_ANIMATION); - } - - @Override - public void onAnimationCancel(Animator animation) { - transform.cancelTransitions(); - } - - @Override - public void onAnimationEnd(Animator animation) { - cameraChangeDispatcher.onCameraIdle(); - } - }); - return animator; - } - private double getNewZoom(float scaleFactor, boolean quickZoom) { double zoomBy = Math.log(scaleFactor) / Math.log(Math.PI / 2); if (quickZoom) { @@ -776,16 +748,95 @@ public boolean onMultiFingerTap(MultiFingerTapGestureDetector detector, int poin transform.cancelTransitions(); cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); + PointF zoomFocalPoint; + // Single finger double tap if (focalPoint != null) { - transform.zoomOut(focalPoint); + // User provided focal point + zoomFocalPoint = focalPoint; } else { - transform.zoomOut(detector.getFocalPoint()); + // Zoom in on gesture + zoomFocalPoint = detector.getFocalPoint(); } + zoomOutAnimated(zoomFocalPoint, false); + return true; } } + private Animator createScaleAnimator(double currentZoom, double zoomAddition, PointF animationFocalPoint, + long animationTime) { + ValueAnimator animator = ValueAnimator.ofFloat((float) currentZoom, (float) (currentZoom + zoomAddition)); + animator.setDuration(animationTime); + animator.setInterpolator(new DecelerateInterpolator()); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + transform.setZoom((Float) animation.getAnimatedValue(), animationFocalPoint); + } + }); + + animator.addListener(new AnimatorListenerAdapter() { + + @Override + public void onAnimationStart(Animator animation) { + transform.cancelTransitions(); + cameraChangeDispatcher.onCameraMoveStarted(REASON_API_ANIMATION); + } + + @Override + public void onAnimationCancel(Animator animation) { + transform.cancelTransitions(); + } + + @Override + public void onAnimationEnd(Animator animation) { + cameraChangeDispatcher.onCameraIdle(); + } + }); + return animator; + } + + /** + * Zoom in by 1. + * + * @param zoomFocalPoint focal point of zoom animation + * @param runImmediately if true, animation will be started right away, otherwise it will wait until + * {@link MotionEvent#ACTION_UP} is registered. + */ + void zoomInAnimated(PointF zoomFocalPoint, boolean runImmediately) { + zoomAnimated(true, zoomFocalPoint, runImmediately); + } + + /** + * Zoom out by 1. + * + * @param zoomFocalPoint focal point of zoom animation + * @param runImmediately if true, animation will be started right away, otherwise it will wait until + * {@link MotionEvent#ACTION_UP} is registered. + */ + void zoomOutAnimated(PointF zoomFocalPoint, boolean runImmediately) { + zoomAnimated(false, zoomFocalPoint, runImmediately); + } + + private void zoomAnimated(boolean zoomIn, PointF zoomFocalPoint, boolean runImmediately) { + //canceling here as well, because when using a button it will not be canceled automatically by onDown() + cancelAnimator(scaleAnimator); + + double currentZoom = transform.getRawZoom(); + scaleAnimator = createScaleAnimator( + currentZoom, + zoomIn ? 1 : -1, + zoomFocalPoint, + MapboxConstants.ANIMATION_DURATION); + if (runImmediately) { + scaleAnimator.start(); + } else { + scheduleAnimator(scaleAnimator); + } + } + private void sendTelemetryEvent(String eventType, PointF focalPoint) { if (isZoomValid(transform)) { MapEventFactory mapEventFactory = new MapEventFactory(); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java index 7bd74d56a0c..08110ff3263 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java @@ -21,12 +21,14 @@ final class MapKeyListener { private final Transform transform; private final UiSettings uiSettings; + private final MapGestureDetector mapGestureDetector; private TrackballLongPressTimeOut currentTrackballLongPressTimeOut; - MapKeyListener(@NonNull Transform transform, @NonNull UiSettings uiSettings) { + MapKeyListener(Transform transform, UiSettings uiSettings, MapGestureDetector mapGestureDetector) { this.transform = transform; this.uiSettings = uiSettings; + this.mapGestureDetector = mapGestureDetector; } /** @@ -124,7 +126,7 @@ boolean onKeyLongPress(int keyCode, KeyEvent event) { // Zoom out PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); - transform.zoomOut(focalPoint); + mapGestureDetector.zoomOutAnimated(focalPoint, true); return true; default: @@ -160,7 +162,7 @@ boolean onKeyUp(int keyCode, KeyEvent event) { // Zoom in PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); - transform.zoomIn(focalPoint); + mapGestureDetector.zoomInAnimated(focalPoint, true); return true; } @@ -215,7 +217,7 @@ boolean onTrackballEvent(MotionEvent event) { if (currentTrackballLongPressTimeOut != null) { // Zoom in PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); - transform.zoomIn(focalPoint); + mapGestureDetector.zoomInAnimated(focalPoint, true); } return true; @@ -257,7 +259,7 @@ public void run() { if (!cancelled) { // Zoom out PointF pointF = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); - transform.zoomOut(pointF); + mapGestureDetector.zoomOutAnimated(pointF, true); // Ensure the up action is not run currentTrackballLongPressTimeOut = null; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index e86829c3e4b..4f5ce2c9266 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -29,7 +29,6 @@ import com.mapbox.android.telemetry.MapEventFactory; import com.mapbox.android.telemetry.MapboxTelemetry; import com.mapbox.mapboxsdk.BuildConfig; - import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.annotations.Annotation; import com.mapbox.mapboxsdk.annotations.MarkerViewManager; @@ -177,12 +176,12 @@ private void initialiseMap() { // user input mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, annotationManager, cameraChangeDispatcher); - mapKeyListener = new MapKeyListener(transform, uiSettings); + mapKeyListener = new MapKeyListener(transform, uiSettings, mapGestureDetector); // overlain zoom buttons mapZoomButtonController = new MapZoomButtonController(new ZoomButtonsController(this)); - MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform, - cameraChangeDispatcher, getWidth(), getHeight()); + MapZoomControllerListener zoomListener = new MapZoomControllerListener( + mapGestureDetector, cameraChangeDispatcher, getWidth(), getHeight()); mapZoomButtonController.bind(uiSettings, zoomListener); compassView.injectCompassAnimationListener(createCompassAnimationListener(cameraChangeDispatcher)); @@ -1030,17 +1029,13 @@ public void setGesturesManager(AndroidGesturesManager gesturesManager) { private static class MapZoomControllerListener implements ZoomButtonsController.OnZoomListener { private final MapGestureDetector mapGestureDetector; - private final UiSettings uiSettings; - private final Transform transform; private final CameraChangeDispatcher cameraChangeDispatcher; private final float mapWidth; private final float mapHeight; - MapZoomControllerListener(MapGestureDetector detector, UiSettings uiSettings, Transform transform, - CameraChangeDispatcher dispatcher, float mapWidth, float mapHeight) { + MapZoomControllerListener(MapGestureDetector detector, CameraChangeDispatcher dispatcher, + float mapWidth, float mapHeight) { this.mapGestureDetector = detector; - this.uiSettings = uiSettings; - this.transform = transform; this.cameraChangeDispatcher = dispatcher; this.mapWidth = mapWidth; this.mapHeight = mapHeight; @@ -1064,9 +1059,9 @@ private void onZoom(boolean zoomIn, @Nullable PointF focalPoint) { focalPoint = new PointF(mapWidth / 2, mapHeight / 2); } if (zoomIn) { - transform.zoomIn(focalPoint); + mapGestureDetector.zoomInAnimated(focalPoint, true); } else { - transform.zoomOut(focalPoint); + mapGestureDetector.zoomOutAnimated(focalPoint, true); } } } 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 c226833f3ef..83f853bfc2e 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 @@ -226,24 +226,8 @@ void setOnCameraChangeListener(@Nullable MapboxMap.OnCameraChangeListener listen return mapView.getZoom(); } - void zoomIn(@NonNull PointF focalPoint) { - CameraPosition cameraPosition = invalidateCameraPosition(); - if (cameraPosition != null) { - int newZoom = (int) Math.round(cameraPosition.zoom + 1); - setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION); - } - } - - void zoomOut(@NonNull PointF focalPoint) { - CameraPosition cameraPosition = invalidateCameraPosition(); - if (cameraPosition != null) { - int newZoom = (int) Math.round(cameraPosition.zoom - 1); - setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION); - } - } - void zoomBy(double zoomAddition, @NonNull PointF focalPoint) { - setZoom(mapView.getZoom() + zoomAddition, focalPoint, 0); + setZoom(mapView.getZoom() + zoomAddition, focalPoint); } void setZoom(double zoom, @NonNull PointF focalPoint) {