summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorŁukasz Paczos <lukas.paczos@gmail.com>2019-07-16 12:46:27 +0200
committerŁukasz Paczos <lukasz.paczos@mapbox.com>2019-08-15 18:08:29 +0300
commit3e73e4d49fd4239d8dc12584294e6ea3d200facf (patch)
tree978d93f5d9eefbd5ed1653c3608976301c7dd92b
parent18971395d67d5014f571035382762f51be6ff2fb (diff)
downloadqtlocation-mapboxgl-3e73e4d49fd4239d8dc12584294e6ea3d200facf.tar.gz
[android] improve scale + rotation behavior
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java103
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java29
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java16
5 files changed, 103 insertions, 51 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 e9fc9e2e02..d5c5c4d999 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
@@ -200,5 +200,6 @@ public class MapboxConstants {
public static final String STATE_ROTATE_ANIMATION_ENABLED = "mapbox_rotateAnimationEnabled";
public static final String STATE_FLING_ANIMATION_ENABLED = "mapbox_flingAnimationEnabled";
public static final String STATE_INCREASE_ROTATE_THRESHOLD = "mapbox_increaseRotateThreshold";
+ public static final String STATE_DISABLE_ROTATE_WHEN_SCALING = "mapbox_disableRotateWhenScaling";
public static final String STATE_INCREASE_SCALE_THRESHOLD = "mapbox_increaseScaleThreshold";
}
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 77d59e1690..6b61f01b8a 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
@@ -13,7 +13,6 @@ import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import com.mapbox.android.gestures.AndroidGesturesManager;
-import com.mapbox.android.gestures.Constants;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.android.gestures.MultiFingerTapGestureDetector;
import com.mapbox.android.gestures.RotateGestureDetector;
@@ -115,12 +114,12 @@ 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_minimum_scale_velocity));
+ 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_minimum_scale_span_when_rotating),
- context.getResources().getDimension(R.dimen.mapbox_minimum_angular_velocity),
- context.getResources().getDimension(
- com.mapbox.android.gestures.R.dimen.mapbox_defaultScaleSpanSinceStartThreshold));
+ context.getResources().getDimension(R.dimen.mapbox_minimum_angular_velocity));
ShoveGestureListener shoveGestureListener = new ShoveGestureListener();
TapGestureListener tapGestureListener = new TapGestureListener();
@@ -152,6 +151,7 @@ final class MapGestureDetector {
}
gesturesManager = androidGesturesManager;
+ gesturesManager.getRotateGestureDetector().setAngleThreshold(3f);
}
/**
@@ -480,10 +480,14 @@ final class MapGestureDetector {
private final class ScaleGestureListener extends StandardScaleGestureDetector.SimpleStandardOnScaleGestureListener {
+ private final float minimumGestureSpeed;
+ private final float minimumAngledGestureSpeed;
private final float minimumVelocity;
private boolean quickZoom;
- ScaleGestureListener(float minimumVelocity) {
+ ScaleGestureListener(float minimumGestureSpeed, float minimumAngledGestureSpeed, float minimumVelocity) {
+ this.minimumGestureSpeed = minimumGestureSpeed;
+ this.minimumAngledGestureSpeed = minimumAngledGestureSpeed;
this.minimumVelocity = minimumVelocity;
}
@@ -501,18 +505,38 @@ final class MapGestureDetector {
}
// re-try disabling the move detector in case double tap has been interrupted before quickzoom started
gesturesManager.getMoveGestureDetector().setEnabled(false);
+ } else {
+ if (detector.getPreviousSpan() > 0) {
+ float currSpan = detector.getCurrentSpan();
+ float prevSpan = detector.getPreviousSpan();
+ double currTime = detector.getCurrentEvent().getEventTime();
+ double prevTime = detector.getPreviousEvent().getEventTime();
+ if (currTime == prevTime) {
+ return false;
+ }
+ double speed = Math.abs(currSpan - prevSpan) / (currTime - prevTime);
+ if (speed < minimumGestureSpeed) {
+ // do not scale if the minimal gesture speed is not met
+ return false;
+ } else if (!gesturesManager.getRotateGestureDetector().isInProgress()) {
+ float rotationDeltaSinceLast = gesturesManager.getRotateGestureDetector().getDeltaSinceLast();
+ if (Math.abs(rotationDeltaSinceLast) > 0.4 && speed < minimumAngledGestureSpeed) {
+ // do not scale in case we're preferring to start rotation
+ return false;
+ }
+
+ if (uiSettings.isDisableRotateWhenScaling()) {
+ // disable rotate gesture when scale is detected first
+ gesturesManager.getRotateGestureDetector().setEnabled(false);
+ }
+ }
+ } else {
+ return false;
+ }
}
cancelTransitionsIfRequired();
- if (uiSettings.isIncreaseRotateThresholdWhenScaling()) {
- // increase rotate angle threshold when scale is detected first
- gesturesManager.getRotateGestureDetector().setAngleThreshold(
- Constants.DEFAULT_ROTATE_ANGLE_THRESHOLD
- + MapboxConstants.ROTATION_THRESHOLD_INCREASE_WHEN_SCALING
- );
- }
-
notifyOnScaleBeginListeners(detector);
return true;
@@ -538,13 +562,9 @@ final class MapGestureDetector {
if (quickZoom) {
// re-enabled the move detector if the quickzoom happened
gesturesManager.getMoveGestureDetector().setEnabled(true);
- }
-
- if (uiSettings.isIncreaseRotateThresholdWhenScaling()) {
- // resetting default angle threshold
- gesturesManager.getRotateGestureDetector().setAngleThreshold(
- Constants.DEFAULT_ROTATE_ANGLE_THRESHOLD
- );
+ } else {
+ // re-enable rotation in case it's been disabled
+ gesturesManager.getRotateGestureDetector().setEnabled(true);
}
notifyOnScaleEndListeners(detector);
@@ -605,15 +625,10 @@ final class MapGestureDetector {
}
private final class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
- private final float minimumScaleSpanWhenRotating;
private final float minimumAngularVelocity;
- private final float defaultSpanSinceStartThreshold;
- RotateGestureListener(float minimumScaleSpanWhenRotating, float minimumAngularVelocity,
- float defaultSpanSinceStartThreshold) {
- this.minimumScaleSpanWhenRotating = minimumScaleSpanWhenRotating;
+ RotateGestureListener(float minimumAngularVelocity) {
this.minimumAngularVelocity = minimumAngularVelocity;
- this.defaultSpanSinceStartThreshold = defaultSpanSinceStartThreshold;
}
@Override
@@ -622,15 +637,26 @@ final class MapGestureDetector {
return false;
}
- cancelTransitionsIfRequired();
-
- if (uiSettings.isIncreaseScaleThresholdWhenRotating()) {
- // when rotation starts, interrupting scale and increasing the threshold
- // to make rotation without scaling easier
- gesturesManager.getStandardScaleGestureDetector().setSpanSinceStartThreshold(minimumScaleSpanWhenRotating);
- gesturesManager.getStandardScaleGestureDetector().interrupt();
+ float deltaSinceLast = Math.abs(detector.getDeltaSinceLast());
+ double currTime = detector.getCurrentEvent().getEventTime();
+ double prevTime = detector.getPreviousEvent().getEventTime();
+ if (currTime == prevTime) {
+ return false;
+ }
+ double speed = deltaSinceLast / (currTime - prevTime);
+ float deltaSinceStart = Math.abs(detector.getDeltaSinceStart());
+
+ // adjust the responsiveness of a rotation gesture - the higher the speed, the bigger the threshold
+ if (speed < 0.04
+ || (speed > 0.07 && deltaSinceStart < 5)
+ || (speed > 0.15 && deltaSinceStart < 7)
+ || (speed > 0.5 && deltaSinceStart < 15)
+ ) {
+ return false;
}
+ cancelTransitionsIfRequired();
+
notifyOnRotateBeginListeners(detector);
return true;
@@ -657,11 +683,6 @@ final class MapGestureDetector {
@Override
public void onRotateEnd(@NonNull RotateGestureDetector detector, float velocityX,
float velocityY, float angularVelocity) {
- if (uiSettings.isIncreaseScaleThresholdWhenRotating()) {
- // resetting default scale threshold values
- gesturesManager.getStandardScaleGestureDetector().setSpanSinceStartThreshold(defaultSpanSinceStartThreshold);
- }
-
notifyOnRotateEndListeners(detector);
if (!uiSettings.isRotateVelocityAnimationEnabled() || Math.abs(angularVelocity) < minimumAngularVelocity) {
@@ -681,6 +702,8 @@ final class MapGestureDetector {
angularVelocity = -angularVelocity;
}
+ // todo clear scale velocity if angular velocity exceeds a threshold
+
PointF focalPoint = getRotateFocalPoint(detector);
rotateAnimator = createRotateAnimator(angularVelocity, animationTime, focalPoint);
scheduleAnimator(rotateAnimator);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
index 49abb70c91..4c4ced8804 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
@@ -67,6 +67,7 @@ public final class UiSettings {
private boolean flingVelocityAnimationEnabled = true;
private boolean increaseRotateThresholdWhenScaling = true;
+ private boolean disableRotateWhenScaling = true;
private boolean increaseScaleThresholdWhenRotating = true;
private float zoomRate = 1.0f;
@@ -132,6 +133,7 @@ public final class UiSettings {
outState.putBoolean(MapboxConstants.STATE_ROTATE_ANIMATION_ENABLED, isRotateVelocityAnimationEnabled());
outState.putBoolean(MapboxConstants.STATE_FLING_ANIMATION_ENABLED, isFlingVelocityAnimationEnabled());
outState.putBoolean(MapboxConstants.STATE_INCREASE_ROTATE_THRESHOLD, isIncreaseRotateThresholdWhenScaling());
+ outState.putBoolean(MapboxConstants.STATE_DISABLE_ROTATE_WHEN_SCALING, isDisableRotateWhenScaling());
outState.putBoolean(MapboxConstants.STATE_INCREASE_SCALE_THRESHOLD, isIncreaseScaleThresholdWhenRotating());
outState.putBoolean(MapboxConstants.STATE_QUICK_ZOOM_ENABLED, isQuickZoomGesturesEnabled());
outState.putFloat(MapboxConstants.STATE_ZOOM_RATE, getZoomRate());
@@ -148,6 +150,7 @@ public final class UiSettings {
setFlingVelocityAnimationEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_FLING_ANIMATION_ENABLED));
setIncreaseRotateThresholdWhenScaling(
savedInstanceState.getBoolean(MapboxConstants.STATE_INCREASE_ROTATE_THRESHOLD));
+ setDisableRotateWhenScaling(savedInstanceState.getBoolean(MapboxConstants.STATE_DISABLE_ROTATE_WHEN_SCALING));
setIncreaseScaleThresholdWhenRotating(
savedInstanceState.getBoolean(MapboxConstants.STATE_INCREASE_SCALE_THRESHOLD));
setQuickZoomGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_QUICK_ZOOM_ENABLED));
@@ -919,7 +922,9 @@ public final class UiSettings {
* Returns whether rotation threshold should be increase whenever scale is detected.
*
* @return If true, rotation threshold will be increased.
+ * @deprecated unused, see {@link #isDisableRotateWhenScaling()} instead
*/
+ @Deprecated
public boolean isIncreaseRotateThresholdWhenScaling() {
return increaseRotateThresholdWhenScaling;
}
@@ -928,16 +933,38 @@ public final class UiSettings {
* Set whether rotation threshold should be increase whenever scale is detected.
*
* @param increaseRotateThresholdWhenScaling If true, rotation threshold will be increased.
+ * @deprecated unused, see {@link #setDisableRotateWhenScaling(boolean)} instead
*/
+ @Deprecated
public void setIncreaseRotateThresholdWhenScaling(boolean increaseRotateThresholdWhenScaling) {
this.increaseRotateThresholdWhenScaling = increaseRotateThresholdWhenScaling;
}
/**
+ * Returns whether rotation gesture detector is disabled when scale is detected first.
+ *
+ * @return If true, rotation gesture detector will be disabled when scale is detected first.
+ */
+ public boolean isDisableRotateWhenScaling() {
+ return disableRotateWhenScaling;
+ }
+
+ /**
+ * Set whether rotation gesture detector should be disabled when scale is detected first.
+ *
+ * @param disableRotateWhenScaling If true, rotation gesture detector will be disabled when scale is detected first.
+ */
+ public void setDisableRotateWhenScaling(boolean disableRotateWhenScaling) {
+ this.disableRotateWhenScaling = disableRotateWhenScaling;
+ }
+
+ /**
* Returns whether scale threshold should be increase whenever rotation is detected.
*
* @return If true, scale threshold will be increased.
+ * @deprecated unused
*/
+ @Deprecated
public boolean isIncreaseScaleThresholdWhenRotating() {
return increaseScaleThresholdWhenRotating;
}
@@ -946,7 +973,9 @@ public final class UiSettings {
* set whether scale threshold should be increase whenever rotation is detected.
*
* @param increaseScaleThresholdWhenRotating If true, scale threshold will be increased.
+ * @deprecated unused
*/
+ @Deprecated
public void setIncreaseScaleThresholdWhenRotating(boolean increaseScaleThresholdWhenRotating) {
this.increaseScaleThresholdWhenRotating = increaseScaleThresholdWhenRotating;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
index 161a9634d2..018750400c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
@@ -3,6 +3,8 @@
<dimen name="mapbox_infowindow_tipview_width">8dp</dimen>
<dimen name="mapbox_infowindow_margin">8dp</dimen>
<dimen name="mapbox_four_dp">4dp</dimen>
+ <dimen name="mapbox_minimum_scale_speed">0.6dp</dimen>
+ <dimen name="mapbox_minimum_angled_scale_speed">0.9dp</dimen>
<dimen name="mapbox_eight_dp">8dp</dimen>
<dimen name="mapbox_ninety_two_dp">92dp</dimen>
<dimen name="mapbox_my_locationview_outer_circle">18dp</dimen>
@@ -10,9 +12,6 @@
<!--Minimum scale velocity required to start animation-->
<dimen name="mapbox_minimum_scale_velocity">225dp</dimen>
- <!--Minimum scale span delta required to execute scale gesture when rotating-->
- <dimen name="mapbox_minimum_scale_span_when_rotating">100dp</dimen>
-
<!--Minimum angular velocity required to start rotation animation-->
<dimen name="mapbox_minimum_angular_velocity">0.025dp</dimen>
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
index 80ac2213ee..cfcf0a0486 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
@@ -341,17 +341,17 @@ public class UiSettingsTest {
}
@Test
- public void testIncreaseRotateThresholdWhenScalingEnabled() {
- uiSettings.setIncreaseRotateThresholdWhenScaling(true);
- assertEquals("Rotate threshold increase should be enabled", true,
- uiSettings.isIncreaseRotateThresholdWhenScaling());
+ public void testDisableRotateWhenScalingEnabled() {
+ uiSettings.setDisableRotateWhenScaling(true);
+ assertEquals("Rotate disabling should be enabled", true,
+ uiSettings.isDisableRotateWhenScaling());
}
@Test
- public void testIncreaseRotateThresholdWhenScalingDisabled() {
- uiSettings.setIncreaseRotateThresholdWhenScaling(false);
- assertEquals("Rotate threshold increase should be disabled", false,
- uiSettings.isIncreaseRotateThresholdWhenScaling());
+ public void testDisableRotateWhenScalingDisabled() {
+ uiSettings.setDisableRotateWhenScaling(false);
+ assertEquals("Rotate disabling should be disabled", false,
+ uiSettings.isDisableRotateWhenScaling());
}
@Test