Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Execute quickzoom scale change based on the Y axis delta change #15386

Merged
merged 1 commit into from
Aug 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ public class MapboxConstants {
*/
public static final double MAX_ABSOLUTE_SCALE_VELOCITY_CHANGE = 2.5;

/**
* Maximum possible zoom change during the quick zoom gesture executed across the whole screen
*/
public static final double QUICK_ZOOM_MAX_ZOOM_CHANGE = 4.0;

/**
* Scale velocity animation duration multiplier.
*/
Expand Down Expand Up @@ -156,12 +161,18 @@ public class MapboxConstants {

/**
* The currently used minimum scale factor to clamp to when a quick zoom gesture occurs
*
* @deprecated unused
*/
@Deprecated
public static final float MINIMUM_SCALE_FACTOR_CLAMP = 0.00f;

/**
* The currently used maximum scale factor to clamp to when a quick zoom gesture occurs
*
* @deprecated unused
*/
@Deprecated
public static final float MAXIMUM_SCALE_FACTOR_CLAMP = 0.15f;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PointF;
import android.os.Handler;
import android.support.annotation.NonNull;
Expand Down Expand Up @@ -31,11 +32,13 @@

import static com.mapbox.mapboxsdk.constants.MapboxConstants.MAXIMUM_ANGULAR_VELOCITY;
import static com.mapbox.mapboxsdk.constants.MapboxConstants.MAX_ABSOLUTE_SCALE_VELOCITY_CHANGE;
import static com.mapbox.mapboxsdk.constants.MapboxConstants.QUICK_ZOOM_MAX_ZOOM_CHANGE;
import static com.mapbox.mapboxsdk.constants.MapboxConstants.ROTATE_VELOCITY_RATIO_THRESHOLD;
import static com.mapbox.mapboxsdk.constants.MapboxConstants.SCALE_VELOCITY_ANIMATION_DURATION_MULTIPLIER;
import static com.mapbox.mapboxsdk.constants.MapboxConstants.SCALE_VELOCITY_RATIO_THRESHOLD;
import static com.mapbox.mapboxsdk.constants.MapboxConstants.ZOOM_RATE;
import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE;
import static com.mapbox.mapboxsdk.utils.MathUtils.normalize;

/**
* Manages gestures events on a MapView.
Expand Down Expand Up @@ -76,6 +79,9 @@ final class MapGestureDetector {
@Nullable
private PointF constantFocalPoint;

@NonNull
private PointF doubleTapFocalPoint = new PointF();

private AndroidGesturesManager gesturesManager;

private Animator scaleAnimator;
Expand Down Expand Up @@ -321,8 +327,6 @@ boolean onGenericMotionEvent(MotionEvent event) {
}

private final class StandardGestureListener extends StandardGestureDetector.SimpleStandardOnGestureListener {

private PointF doubleTapFocalPoint;
private final float doubleTapMovementThreshold;

StandardGestureListener(float doubleTapMovementThreshold) {
Expand Down Expand Up @@ -495,6 +499,8 @@ private final class ScaleGestureListener extends StandardScaleGestureDetector.Si
private final double scaleVelocityRatioThreshold;
private boolean quickZoom;
private float spanSinceLast;
private double screenHeight;
private double startZoom;

ScaleGestureListener(double densityMultiplier, float minimumGestureSpeed, float minimumAngledGestureSpeed,
float minimumVelocity) {
Expand Down Expand Up @@ -548,6 +554,9 @@ public boolean onScaleBegin(@NonNull StandardScaleGestureDetector detector) {
}
}

screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
startZoom = transform.getRawZoom();

cancelTransitionsIfRequired();

notifyOnScaleBeginListeners(detector);
Expand All @@ -562,10 +571,24 @@ public boolean onScale(@NonNull StandardScaleGestureDetector detector) {
// dispatching camera start event only when the movement actually occurred
cameraChangeDispatcher.onCameraMoveStarted(CameraChangeDispatcher.REASON_API_GESTURE);

float scaleFactor = detector.getScaleFactor();
double zoomBy = getNewZoom(scaleFactor, quickZoom);
PointF focalPoint = getScaleFocalPoint(detector);
transform.zoomBy(zoomBy, focalPoint);
if (quickZoom) {
double pixelDeltaChange = Math.abs(detector.getCurrentEvent().getY() - doubleTapFocalPoint.y);
boolean zoomedOut = detector.getCurrentEvent().getY() < doubleTapFocalPoint.y;

// normalize the pixel delta change, ranging from 0 to screen height, to a constant zoom change range
double normalizedDeltaChange = normalize(pixelDeltaChange, 0, screenHeight, 0, QUICK_ZOOM_MAX_ZOOM_CHANGE);

// calculate target zoom and adjust for a multiplier
double targetZoom = (zoomedOut ? startZoom - normalizedDeltaChange : startZoom + normalizedDeltaChange);
targetZoom *= uiSettings.getZoomRate();

transform.setZoom(targetZoom, focalPoint);
} else {
double zoomBy =
(Math.log(detector.getScaleFactor()) / Math.log(Math.PI / 2)) * ZOOM_RATE * uiSettings.getZoomRate();
transform.zoomBy(zoomBy, focalPoint);
}

notifyOnScaleListeners(detector);

Expand Down Expand Up @@ -628,19 +651,6 @@ private double calculateScale(double velocityXY, boolean isScalingOut) {
}
return zoomAddition;
}

private double getNewZoom(float scaleFactor, boolean quickZoom) {
double zoomBy = (Math.log(scaleFactor) / Math.log(Math.PI / 2)) * ZOOM_RATE * uiSettings.getZoomRate();
if (quickZoom) {
// clamp scale factors we feed to core #7514
boolean negative = zoomBy < 0;
zoomBy = MathUtils.clamp(Math.abs(zoomBy),
MapboxConstants.MINIMUM_SCALE_FACTOR_CLAMP,
MapboxConstants.MAXIMUM_SCALE_FACTOR_CLAMP);
return negative ? -zoomBy : zoomBy;
}
return zoomBy;
}
}

private final class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,19 @@ public static double wrap(double value, double min, double max) {

return secondMod + min;
}

/**
* Scale a value from an arbitrary range to a normalized range.
*
* @param x The value to be normalized.
* @param dataLow lowest expected value from a data set
* @param dataHigh highest expected value from a data set
* @param normalizedLow normalized lowest value
* @param normalizedHigh normalized highest value
* @return The result of the normalization.
*/
public static double normalize(double x, double dataLow, double dataHigh,
double normalizedLow, double normalizedHigh) {
return ((x - dataLow) / (dataHigh - dataLow)) * (normalizedHigh - normalizedLow) + normalizedLow;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,18 @@ class MapGestureDetectorTest : BaseTest() {
Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
}
}

@Test
fun quickZoom_roundTripping() {
validateTestSetup()
rule.runOnUiThread {
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(51.0, 16.0), 3.0))
}
onView(withId(R.id.mapView)).perform(quickScale(300f, withVelocity = false, duration = 750L))
onView(withId(R.id.mapView)).perform(quickScale(-300f, withVelocity = false, duration = 750L))

rule.runOnUiThread {
Assert.assertEquals(3.0, mapboxMap.cameraPosition.zoom, 0.0001)
}
}
}