Skip to content

Commit 2e0b464

Browse files
set default move gesture threshold to a small non-zero value (#3573)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 1899cde commit 2e0b464

File tree

5 files changed

+42
-52
lines changed

5 files changed

+42
-52
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
- [core] Fix memory access violation exception in vector_tile_data.cpp [#632](https://github.com/maplibre/maplibre-native/pull/632)
3232
- [iOS] Fix a bug where the compass was determined to be misplaced when hidden [#498](https://github.com/maplibre/maplibre-native/pull/498).
3333
- [core] `MaptilerFileSource` renamed to `MBTilesFileSource` [#198](https://github.com/maplibre/maplibre-native/pull/198).
34+
- [android] Fix `OnMoveListener::onMoveBegin` was always called even on a simple tap. [#2792](https://github.com/maplibre/maplibre-native/issues/2792)
35+
In case you rely on the old behavior, call `maplibreMap.getGesturesManager().getMoveGestureDetector().setMoveThreshold(0f)` to restore it
3436

3537
## maps-v1.6.0
3638

platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/location/LocationCameraController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,8 @@ private void adjustGesturesThresholds() {
314314
if (isLocationTracking()) {
315315
moveGestureDetector.setMoveThreshold(options.trackingInitialMoveThreshold());
316316
} else {
317-
moveGestureDetector.setMoveThreshold(0f);
317+
float initialMoveThreshold = initialGesturesManager.getMoveGestureDetector().getMoveThreshold();
318+
moveGestureDetector.setMoveThreshold(initialMoveThreshold);
318319
moveGestureDetector.setMoveThresholdRect(null);
319320
}
320321
}

platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapGestureDetector.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,15 @@ private void initializeGesturesManager(@NonNull AndroidGesturesManager androidGe
169169
androidGesturesManager.setMutuallyExclusiveGestures(shoveScaleSet, shoveRotateSet, ScaleLongPressSet);
170170
}
171171

172+
// If this was 0°, every shove gesture (for tilting the map) would be detected as also a rotate
173+
androidGesturesManager.getRotateGestureDetector().setAngleThreshold(3f);
174+
175+
// If this was 0 (the default), a simple tap would also be detected as a move. A (very) small
176+
// move threshold solves this issue, while not making the map feel "sticky". (See #2792)
177+
androidGesturesManager.getMoveGestureDetector().setMoveThresholdResource(R.dimen.maplibre_minimum_move_threshold);
178+
172179
gesturesManager = androidGesturesManager;
173-
gesturesManager.getRotateGestureDetector().setAngleThreshold(3f);
180+
174181
}
175182

176183
/**

platform/android/MapLibreAndroid/src/main/res/values/dimens.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
<!--Screen density constant to adjust gesture's velocityXY thresholds-->
2525
<dimen name="maplibre_density_constant">0.29dp</dimen>
2626

27+
<!--Threshold until a move is detected as such-->
28+
<dimen name="maplibre_minimum_move_threshold">4dp</dimen>
29+
30+
<!--Threshold until a move is detected as such during camera location tracking -->
2731
<dimen name="maplibre_locationComponentTrackingInitialMoveThreshold">25dp</dimen>
2832
<dimen name="maplibre_locationComponentTrackingMultiFingerMoveThreshold">400dp</dimen>
2933
</resources>

platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/location/LocationCameraControllerTest.kt

Lines changed: 26 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class LocationCameraControllerTest {
9494
camera.initializeOptions(options)
9595
camera.cameraMode = CameraMode.NONE
9696
Mockito.verify(moveGestureDetector, Mockito.times(2)).moveThreshold =
97-
0f // one for initialization
97+
MOVEMENT_THRESHOLD // one for initialization
9898
Mockito.verify(moveGestureDetector, Mockito.times(2)).moveThresholdRect =
9999
null // one for initialization
100100
}
@@ -698,9 +698,7 @@ class LocationCameraControllerTest {
698698
@Test
699699
fun gesturesManagement_enabled() {
700700
val maplibreMap = Mockito.mock(MapLibreMap::class.java)
701-
val initialGesturesManager = Mockito.mock(
702-
AndroidGesturesManager::class.java
703-
)
701+
val initialGesturesManager = buildInitialGesturesManager()
704702
val internalGesturesManager = Mockito.mock(
705703
AndroidGesturesManager::class.java
706704
)
@@ -717,9 +715,7 @@ class LocationCameraControllerTest {
717715
@Test
718716
fun gesturesManagement_disabled() {
719717
val maplibreMap = Mockito.mock(MapLibreMap::class.java)
720-
val initialGesturesManager = Mockito.mock(
721-
AndroidGesturesManager::class.java
722-
)
718+
val initialGesturesManager = buildInitialGesturesManager()
723719
val internalGesturesManager = Mockito.mock(
724720
AndroidGesturesManager::class.java
725721
)
@@ -736,9 +732,7 @@ class LocationCameraControllerTest {
736732
@Test
737733
fun gesturesManagement_optionNotChangedInitial() {
738734
val maplibreMap = Mockito.mock(MapLibreMap::class.java)
739-
val initialGesturesManager = Mockito.mock(
740-
AndroidGesturesManager::class.java
741-
)
735+
val initialGesturesManager = buildInitialGesturesManager()
742736
val internalGesturesManager = Mockito.mock(
743737
AndroidGesturesManager::class.java
744738
)
@@ -756,9 +750,7 @@ class LocationCameraControllerTest {
756750
@Test
757751
fun gesturesManagement_optionNotChangedInternal() {
758752
val maplibreMap = Mockito.mock(MapLibreMap::class.java)
759-
val initialGesturesManager = Mockito.mock(
760-
AndroidGesturesManager::class.java
761-
)
753+
val initialGesturesManager = buildInitialGesturesManager()
762754
val internalGesturesManager = Mockito.mock(
763755
AndroidGesturesManager::class.java
764756
)
@@ -792,7 +784,7 @@ class LocationCameraControllerTest {
792784
Mockito.`when`(options.trackingMultiFingerProtectedMoveArea()).thenReturn(multiFingerArea)
793785
camera.initializeOptions(options)
794786
camera.onMoveListener.onMoveBegin(moveGestureDetector)
795-
Mockito.verify(moveGestureDetector, Mockito.times(2)).moveThreshold = 0f
787+
Mockito.verify(moveGestureDetector, Mockito.times(2)).moveThreshold = MOVEMENT_THRESHOLD
796788
Mockito.verify(moveGestureDetector, Mockito.times(2)).moveThresholdRect = null
797789
}
798790

@@ -876,12 +868,8 @@ class LocationCameraControllerTest {
876868
Mockito.verify(moveGestureDetector, Mockito.times(2)).interrupt()
877869

878870
// verify that threshold are reset
879-
val moveThresholdCaptor = ArgumentCaptor.forClass(
880-
Float::class.java
881-
)
882871
Mockito.verify(moveGestureDetector, Mockito.atLeastOnce()).moveThreshold =
883-
moveThresholdCaptor.capture()
884-
org.junit.Assert.assertEquals(java.lang.Float.valueOf(0f), moveThresholdCaptor.value)
872+
MOVEMENT_THRESHOLD
885873
}
886874

887875
@Test
@@ -973,18 +961,9 @@ class LocationCameraControllerTest {
973961
Mockito.verify(moveGestureDetector, Mockito.times(2)).interrupt()
974962

975963
// verify that threshold are reset
976-
val moveThresholdCaptor = ArgumentCaptor.forClass(
977-
Float::class.java
978-
)
979964
Mockito.verify(moveGestureDetector, Mockito.atLeastOnce()).moveThreshold =
980-
moveThresholdCaptor.capture()
981-
org.junit.Assert.assertEquals(java.lang.Float.valueOf(0f), moveThresholdCaptor.value)
982-
val areaCaptor = ArgumentCaptor.forClass(
983-
RectF::class.java
984-
)
985-
Mockito.verify(moveGestureDetector, Mockito.atLeastOnce()).moveThresholdRect =
986-
areaCaptor.capture()
987-
org.junit.Assert.assertNull(areaCaptor.value)
965+
MOVEMENT_THRESHOLD
966+
Mockito.verify(moveGestureDetector, Mockito.atLeastOnce()).moveThresholdRect = null
988967
}
989968

990969
@Test
@@ -1911,9 +1890,6 @@ class LocationCameraControllerTest {
19111890
val onCameraMoveInvalidateListener = Mockito.mock(
19121891
OnCameraMoveInvalidateListener::class.java
19131892
)
1914-
val initialGesturesManager = Mockito.mock(
1915-
AndroidGesturesManager::class.java
1916-
)
19171893
val internalGesturesManager = Mockito.mock(
19181894
AndroidGesturesManager::class.java
19191895
)
@@ -1923,7 +1899,7 @@ class LocationCameraControllerTest {
19231899
moveGestureDetector,
19241900
onCameraTrackingChangedListener,
19251901
onCameraMoveInvalidateListener,
1926-
initialGesturesManager,
1902+
buildInitialGesturesManager(),
19271903
internalGesturesManager
19281904
)
19291905
}
@@ -1955,9 +1931,6 @@ class LocationCameraControllerTest {
19551931
val onCameraMoveInvalidateListener = Mockito.mock(
19561932
OnCameraMoveInvalidateListener::class.java
19571933
)
1958-
val initialGesturesManager = Mockito.mock(
1959-
AndroidGesturesManager::class.java
1960-
)
19611934
val internalGesturesManager = Mockito.mock(
19621935
AndroidGesturesManager::class.java
19631936
)
@@ -1967,7 +1940,7 @@ class LocationCameraControllerTest {
19671940
moveGestureDetector,
19681941
onCameraTrackingChangedListener,
19691942
onCameraMoveInvalidateListener,
1970-
initialGesturesManager,
1943+
buildInitialGesturesManager(),
19711944
internalGesturesManager
19721945
)
19731946
}
@@ -1985,9 +1958,6 @@ class LocationCameraControllerTest {
19851958
val onCameraMoveInvalidateListener = Mockito.mock(
19861959
OnCameraMoveInvalidateListener::class.java
19871960
)
1988-
val initialGesturesManager = Mockito.mock(
1989-
AndroidGesturesManager::class.java
1990-
)
19911961
val internalGesturesManager = Mockito.mock(
19921962
AndroidGesturesManager::class.java
19931963
)
@@ -1997,7 +1967,7 @@ class LocationCameraControllerTest {
19971967
moveGestureDetector,
19981968
onCameraTrackingChangedListener,
19991969
onCameraMoveInvalidateListener,
2000-
initialGesturesManager,
1970+
buildInitialGesturesManager(),
20011971
internalGesturesManager
20021972
)
20031973
}
@@ -2034,9 +2004,6 @@ class LocationCameraControllerTest {
20342004
val onCameraMoveInvalidateListener = Mockito.mock(
20352005
OnCameraMoveInvalidateListener::class.java
20362006
)
2037-
val initialGesturesManager = Mockito.mock(
2038-
AndroidGesturesManager::class.java
2039-
)
20402007
val internalGesturesManager = Mockito.mock(
20412008
AndroidGesturesManager::class.java
20422009
)
@@ -2046,7 +2013,7 @@ class LocationCameraControllerTest {
20462013
moveGestureDetector,
20472014
onCameraTrackingChangedListener,
20482015
onCameraMoveInvalidateListener,
2049-
initialGesturesManager,
2016+
buildInitialGesturesManager(),
20502017
internalGesturesManager
20512018
)
20522019
}
@@ -2066,9 +2033,6 @@ class LocationCameraControllerTest {
20662033
val onCameraMoveInvalidateListener = Mockito.mock(
20672034
OnCameraMoveInvalidateListener::class.java
20682035
)
2069-
val initialGesturesManager = Mockito.mock(
2070-
AndroidGesturesManager::class.java
2071-
)
20722036
val internalGesturesManager = Mockito.mock(
20732037
AndroidGesturesManager::class.java
20742038
)
@@ -2078,7 +2042,7 @@ class LocationCameraControllerTest {
20782042
moveGestureDetector,
20792043
onCameraTrackingChangedListener,
20802044
onCameraMoveInvalidateListener,
2081-
initialGesturesManager,
2045+
buildInitialGesturesManager(),
20822046
internalGesturesManager
20832047
)
20842048
locationCameraController.setEnabled(true)
@@ -2113,6 +2077,18 @@ class LocationCameraControllerTest {
21132077
)
21142078
}
21152079

2080+
private fun buildInitialGesturesManager(): AndroidGesturesManager {
2081+
val moveGestureDetector = Mockito.mock<MoveGestureDetector>()
2082+
// return just "some" value
2083+
Mockito.`when`(moveGestureDetector.moveThreshold).thenReturn(MOVEMENT_THRESHOLD)
2084+
2085+
val manager = Mockito.mock<AndroidGesturesManager>()
2086+
Mockito.`when`(manager.moveGestureDetector).thenReturn(moveGestureDetector)
2087+
return manager
2088+
}
2089+
2090+
private val MOVEMENT_THRESHOLD = 10f
2091+
21162092
private fun <T> getAnimationListener(
21172093
@MapLibreAnimator.Type animatorType: Int,
21182094
holders: Set<AnimatorListenerHolder>

0 commit comments

Comments
 (0)