summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorŁukasz Paczos <lukas.paczos@gmail.com>2019-07-16 18:20:43 +0200
committerŁukasz Paczos <lukasz.paczos@mapbox.com>2019-08-15 18:08:29 +0300
commitacc6079b088c75d279b4e55bd8687edf8916144c (patch)
tree0bb6a6f5d65da1129e6d137dc5882a8a6c5e800f
parent3e73e4d49fd4239d8dc12584294e6ea3d200facf (diff)
downloadqtlocation-mapboxgl-acc6079b088c75d279b4e55bd8687edf8916144c.tar.gz
[android] improve rotation inertia, adjust velocity ratios for screen density
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java20
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java57
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml8
3 files changed, 53 insertions, 32 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
index d5c5c4d999..015260322c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
@@ -74,11 +74,6 @@ public class MapboxConstants {
public static final long VELOCITY_THRESHOLD_IGNORE_FLING = 1000;
/**
- * Value by which the default rotation threshold will be increased when scaling
- */
- public static final float ROTATION_THRESHOLD_INCREASE_WHEN_SCALING = 25f;
-
- /**
* Maximum absolute zoom change for multi-pointer scale velocity animation
*/
public static final double MAX_ABSOLUTE_SCALE_VELOCITY_CHANGE = 2.5;
@@ -89,19 +84,24 @@ public class MapboxConstants {
public static final double SCALE_VELOCITY_ANIMATION_DURATION_MULTIPLIER = 150;
/**
- * Time within which user needs to lift fingers for velocity animation to start.
+ * Last scale span delta to XY velocity ratio required to execute scale velocity animation.
*/
- public static final long SCHEDULED_ANIMATION_TIMEOUT = 150L;
+ public static final double SCALE_VELOCITY_RATIO_THRESHOLD = 4 * 1e-3;
/**
- * Minimum angular velocity for rotation animation
+ * Last rotation delta to XY velocity ratio required to execute rotation velocity animation.
*/
- public static final float MINIMUM_ANGULAR_VELOCITY = 1.5f;
+ public static final double ROTATE_VELOCITY_RATIO_THRESHOLD = 2.2 * 1e-4;
+
+ /**
+ * Time within which user needs to lift fingers for velocity animation to start.
+ */
+ public static final long SCHEDULED_ANIMATION_TIMEOUT = 150L;
/**
* Maximum angular velocity for rotation animation
*/
- public static final float MAXIMUM_ANGULAR_VELOCITY = 20f;
+ public static final float MAXIMUM_ANGULAR_VELOCITY = 30f;
/**
* Factor to calculate tilt change based on pixel change during shove gesture.
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 6b61f01b8a..80b1e32413 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
@@ -29,8 +29,11 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
+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.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;
@@ -114,11 +117,14 @@ final class MapGestureDetector {
com.mapbox.android.gestures.R.dimen.mapbox_defaultScaleSpanSinceStartThreshold));
MoveGestureListener moveGestureListener = new MoveGestureListener();
ScaleGestureListener scaleGestureListener = new ScaleGestureListener(
+ context.getResources().getDimension(R.dimen.mapbox_density_constant),
context.getResources().getDimension(R.dimen.mapbox_minimum_scale_speed),
context.getResources().getDimension(R.dimen.mapbox_minimum_angled_scale_speed),
context.getResources().getDimension(R.dimen.mapbox_minimum_scale_velocity)
);
RotateGestureListener rotateGestureListener = new RotateGestureListener(
+ context.getResources().getDimension(R.dimen.mapbox_density_constant),
+ context.getResources().getDimension(R.dimen.mapbox_angular_velocity_multiplier),
context.getResources().getDimension(R.dimen.mapbox_minimum_angular_velocity));
ShoveGestureListener shoveGestureListener = new ShoveGestureListener();
TapGestureListener tapGestureListener = new TapGestureListener();
@@ -258,7 +264,7 @@ final class MapGestureDetector {
};
/**
- * Schedules a velocity animator to be executed when user lift fingers,
+ * Schedules a velocity animator to be executed when user lifts fingers,
* unless canceled by the {@link #cancelAnimatorsRunnable}.
*
* @param animator animator ot be scheduled
@@ -483,12 +489,16 @@ final class MapGestureDetector {
private final float minimumGestureSpeed;
private final float minimumAngledGestureSpeed;
private final float minimumVelocity;
+ private final double scaleVelocityRatioThreshold;
private boolean quickZoom;
+ private float spanSinceLast;
- ScaleGestureListener(float minimumGestureSpeed, float minimumAngledGestureSpeed, float minimumVelocity) {
+ ScaleGestureListener(double densityMultiplier, float minimumGestureSpeed, float minimumAngledGestureSpeed,
+ float minimumVelocity) {
this.minimumGestureSpeed = minimumGestureSpeed;
this.minimumAngledGestureSpeed = minimumAngledGestureSpeed;
this.minimumVelocity = minimumVelocity;
+ this.scaleVelocityRatioThreshold = SCALE_VELOCITY_RATIO_THRESHOLD * densityMultiplier;
}
@Override
@@ -539,6 +549,8 @@ final class MapGestureDetector {
notifyOnScaleBeginListeners(detector);
+ spanSinceLast = Math.abs(detector.getCurrentSpan() - detector.getPreviousSpan());
+
return true;
}
@@ -554,6 +566,8 @@ final class MapGestureDetector {
notifyOnScaleListeners(detector);
+ spanSinceLast = Math.abs(detector.getCurrentSpan() - detector.getPreviousSpan());
+
return true;
}
@@ -571,7 +585,9 @@ final class MapGestureDetector {
float velocityXY = Math.abs(velocityX) + Math.abs(velocityY);
- if (!uiSettings.isScaleVelocityAnimationEnabled() || velocityXY < minimumVelocity) {
+ if (!uiSettings.isScaleVelocityAnimationEnabled()
+ || velocityXY < minimumVelocity
+ || spanSinceLast / velocityXY < scaleVelocityRatioThreshold) {
// notifying listeners that camera is idle only if there is no follow-up animation
dispatchCameraIdle();
return;
@@ -625,10 +641,14 @@ final class MapGestureDetector {
}
private final class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
+ private final float angularVelocityMultiplier;
private final float minimumAngularVelocity;
+ private final double rotateVelocityRatioThreshold;
- RotateGestureListener(float minimumAngularVelocity) {
+ RotateGestureListener(double densityMultiplier, float angularVelocityMultiplier, float minimumAngularVelocity) {
+ this.angularVelocityMultiplier = angularVelocityMultiplier;
this.minimumAngularVelocity = minimumAngularVelocity;
+ this.rotateVelocityRatioThreshold = ROTATE_VELOCITY_RATIO_THRESHOLD * densityMultiplier;
}
@Override
@@ -685,24 +705,23 @@ final class MapGestureDetector {
float velocityY, float angularVelocity) {
notifyOnRotateEndListeners(detector);
- if (!uiSettings.isRotateVelocityAnimationEnabled() || Math.abs(angularVelocity) < minimumAngularVelocity) {
+ angularVelocity = angularVelocity * angularVelocityMultiplier;
+ angularVelocity = MathUtils.clamp(angularVelocity, -MAXIMUM_ANGULAR_VELOCITY, MAXIMUM_ANGULAR_VELOCITY);
+
+ float velocityXY = Math.abs(velocityX) + Math.abs(velocityY);
+ float delta = Math.abs(detector.getDeltaSinceLast());
+ double ratio = delta / velocityXY;
+
+ if (!uiSettings.isRotateVelocityAnimationEnabled()
+ || Math.abs(angularVelocity) < minimumAngularVelocity
+ || (gesturesManager.getStandardScaleGestureDetector().isInProgress() && ratio < rotateVelocityRatioThreshold)) {
// notifying listeners that camera is idle only if there is no follow-up animation
dispatchCameraIdle();
return;
}
- boolean negative = angularVelocity < 0;
- angularVelocity = (float) Math.pow(angularVelocity, 2);
- angularVelocity = MathUtils.clamp(
- angularVelocity, MapboxConstants.MINIMUM_ANGULAR_VELOCITY, MapboxConstants.MAXIMUM_ANGULAR_VELOCITY);
-
- long animationTime = (long) (Math.log(angularVelocity + 1) * 500);
-
- if (negative) {
- angularVelocity = -angularVelocity;
- }
-
- // todo clear scale velocity if angular velocity exceeds a threshold
+ long animationTime = (long) ((Math.log((Math.abs(angularVelocity)) + 1 / Math.pow(Math.E, 2)) + 2)
+ * SCALE_VELOCITY_ANIMATION_DURATION_MULTIPLIER);
PointF focalPoint = getRotateFocalPoint(detector);
rotateAnimator = createRotateAnimator(angularVelocity, animationTime, focalPoint);
@@ -929,10 +948,6 @@ final class MapGestureDetector {
&& (!uiSettings.isTiltGesturesEnabled() || !gesturesManager.getShoveGestureDetector().isInProgress());
}
- private boolean isZoomValid(double mapZoom) {
- return mapZoom >= MapboxConstants.MINIMUM_ZOOM && mapZoom <= MapboxConstants.MAXIMUM_ZOOM;
- }
-
void notifyOnMapClickListeners(@NonNull PointF tapPoint) {
for (MapboxMap.OnMapClickListener listener : onMapClickListenerList) {
if (listener.onMapClick(projection.fromScreenLocation(tapPoint))) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
index 018750400c..b2a0061c5b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
@@ -13,7 +13,13 @@
<dimen name="mapbox_minimum_scale_velocity">225dp</dimen>
<!--Minimum angular velocity required to start rotation animation-->
- <dimen name="mapbox_minimum_angular_velocity">0.025dp</dimen>
+ <dimen name="mapbox_minimum_angular_velocity">0.10dp</dimen>
+
+ <!--Angular velocity multiplier. Adapts the velocity for screen density-->
+ <dimen name="mapbox_angular_velocity_multiplier">1.3dp</dimen>
+
+ <!--Screen density constant to adjust gesture's velocityXY thresholds-->
+ <dimen name="mapbox_density_constant">0.29dp</dimen>
<dimen name="mapbox_locationComponentTrackingInitialMoveThreshold">25dp</dimen>
<dimen name="mapbox_locationComponentTrackingMultiFingerMoveThreshold">400dp</dimen>