[android] - Add touch velocity effects on scale gesture.

This commit is contained in:
Ramin Mirsharifi
2017-10-03 17:51:55 +03:30
committed by Tobrun
parent b8d5798bea
commit 8c4e2f0886
2 changed files with 54 additions and 5 deletions

View File

@@ -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);

View File

@@ -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);
}