From 8c4e2f0886b090946e7c4c0210379080b6bd567c Mon Sep 17 00:00:00 2001 From: Ramin Mirsharifi Date: Tue, 3 Oct 2017 17:51:55 +0330 Subject: [android] - Add touch velocity effects on scale gesture. --- .../mapbox/mapboxsdk/maps/MapGestureDetector.java | 48 +++++++++++++++++++--- .../java/com/mapbox/mapboxsdk/maps/Transform.java | 11 +++++ 2 files changed, 54 insertions(+), 5 deletions(-) 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 f309570a7b..bdc0938456 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 @@ -3,12 +3,14 @@ package com.mapbox.mapboxsdk.maps; import android.content.Context; import android.graphics.PointF; import android.location.Location; +import android.os.Handler; import android.support.annotation.Nullable; import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.ScaleGestureDetectorCompat; import android.view.InputDevice; import android.view.MotionEvent; import android.view.ScaleGestureDetector; +import android.view.VelocityTracker; import android.view.ViewConfiguration; import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector; @@ -59,6 +61,10 @@ final class MapGestureDetector { private boolean recentScaleGestureOccurred; private long scaleBeginTime; + private VelocityTracker velocityTracker = null; + private boolean wasZoomingIn = false; + private final Handler handler = new Handler(); + MapGestureDetector(Context context, Transform transform, Projection projection, UiSettings uiSettings, TrackingSettings trackingSettings, AnnotationManager annotationManager, CameraChangeDispatcher cameraChangeDispatcher) { @@ -153,6 +159,12 @@ final class MapGestureDetector { // Handle two finger tap switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } else { + velocityTracker.clear(); + } + velocityTracker.addMovement(event); // First pointer down, reset scaleGestureOccurred, used to avoid triggering a fling after a scale gesture #7666 recentScaleGestureOccurred = false; transform.setGestureInProgress(true); @@ -180,7 +192,8 @@ final class MapGestureDetector { boolean isTap = tapInterval <= ViewConfiguration.getTapTimeout(); boolean inProgress = rotateGestureDetector.isInProgress() || scaleGestureDetector.isInProgress() - || shoveGestureDetector.isInProgress(); + || shoveGestureDetector.isInProgress() + || scaleGestureOccurred; if (twoTap && isTap && !inProgress) { if (focalPoint != null) { @@ -203,11 +216,23 @@ final class MapGestureDetector { twoTap = false; transform.setGestureInProgress(false); + if (velocityTracker != null) { + velocityTracker.recycle(); + } + velocityTracker = null; break; case MotionEvent.ACTION_CANCEL: twoTap = false; transform.setGestureInProgress(false); + if (velocityTracker != null) { + velocityTracker.recycle(); + } + velocityTracker = null; + break; + case MotionEvent.ACTION_MOVE: + velocityTracker.addMovement(event); + velocityTracker.computeCurrentVelocity(1000); break; } @@ -450,10 +475,22 @@ final class MapGestureDetector { // Called when fingers leave screen @Override public void onScaleEnd(ScaleGestureDetector detector) { - scaleGestureOccurred = false; - scaleBeginTime = 0; - scaleFactor = 1.0f; - cameraChangeDispatcher.onCameraIdle(); + double velocityXY = Math.abs(velocityTracker.getYVelocity()) + Math.abs(velocityTracker.getXVelocity()); + if (velocityXY > MapboxConstants.VELOCITY_THRESHOLD_IGNORE_FLING) { + long animationTime = (long)(Math.log(velocityXY) * 66); + transform.zoom(wasZoomingIn, new PointF(detector.getFocusX(), detector.getFocusY()), animationTime); + handler.postDelayed(new Runnable() { + @Override + public void run() { + scaleGestureOccurred = false; + } + }, animationTime); + } else { + scaleGestureOccurred = false; + scaleBeginTime = 0; + scaleFactor = 1.0f; + cameraChangeDispatcher.onCameraIdle(); + } } // Called each time a finger moves @@ -500,6 +537,7 @@ final class MapGestureDetector { trackingSettings.resetTrackingModesIfRequired(!quickZoom, false, false); // Scale the map + wasZoomingIn = (Math.log(detector.getScaleFactor()) / Math.log(Math.PI / 2)) >= 0; if (focalPoint != null) { // arround user provided focal point transform.zoomBy(Math.log(detector.getScaleFactor()) / Math.log(Math.PI / 2), focalPoint.x, focalPoint.y); 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 6f63c2eba8..026564902c 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 @@ -221,6 +221,17 @@ final class Transform implements MapView.OnMapChangedListener { } } + void zoom(boolean zoomIn, @NonNull PointF focalPoint,long duration) { + CameraPosition cameraPosition = invalidateCameraPosition(); + if (cameraPosition != null) { + int newZoom = (int) Math.round(cameraPosition.zoom + (zoomIn ? 1 : -1)); + setZoom(newZoom, focalPoint, duration); + } else { + // we are not transforming, notify about being idle + cameraChangeDispatcher.onCameraIdle(); + } + } + void setZoom(double zoom, @NonNull PointF focalPoint) { setZoom(zoom, focalPoint, 0); } -- cgit v1.2.1