summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorŁukasz Paczos <lukas.paczos@gmail.com>2018-12-11 19:00:15 +0100
committerŁukasz Paczos <lukas.paczos@gmail.com>2018-12-12 12:32:01 +0100
commit0fe966f83deb52531005f13ae5c7e7f68ae11605 (patch)
treef6ab9eff5c6cb48380058220de89161d926d8e8a
parentd592889e861fa28776ec41a7d9316e2e3ac1a229 (diff)
downloadqtlocation-mapboxgl-upstream/lp-13014-projected-immediate-animation.tar.gz
[android] immediate location animation based on map's projectionupstream/lp-13014-projected-immediate-animation
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinator.java12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinatorTest.kt4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java65
7 files changed, 85 insertions, 13 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinator.java
index b49be5c885..8dd05c3f0c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinator.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinator.java
@@ -13,6 +13,7 @@ import android.view.animation.LinearInterpolator;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.Projection;
import java.util.ArrayList;
import java.util.List;
@@ -39,12 +40,17 @@ final class LocationAnimatorCoordinator {
final List<MapboxAnimator.OnLayerAnimationsValuesChangeListener> layerListeners = new ArrayList<>();
final List<MapboxAnimator.OnCameraAnimationsValuesChangeListener> cameraListeners = new ArrayList<>();
+ private final Projection projection;
private Location previousLocation;
private float previousAccuracyRadius = -1;
private float previousCompassBearing = -1;
private long locationUpdateTimestamp = -1;
private float durationMultiplier;
+ LocationAnimatorCoordinator(Projection projection) {
+ this.projection = projection;
+ }
+
void addLayerListener(MapboxAnimator.OnLayerAnimationsValuesChangeListener listener) {
layerListeners.add(listener);
}
@@ -81,8 +87,8 @@ final class LocationAnimatorCoordinator {
updateLayerAnimators(previousLayerLatLng, targetLatLng, previousLayerBearing, targetLayerBearing);
updateCameraAnimators(previousCameraLatLng, previousCameraBearing, targetLatLng, targetCameraBearing);
- boolean snap = immediateAnimation(previousCameraLatLng, targetLatLng, currentCameraPosition.zoom)
- || immediateAnimation(previousLayerLatLng, targetLatLng, currentCameraPosition.zoom);
+ boolean snap = immediateAnimation(projection, previousCameraLatLng, targetLatLng)
+ || immediateAnimation(projection, previousLayerLatLng, targetLatLng);
playLocationAnimators(snap ? 0 : getAnimationDuration());
previousLocation = newLocation;
@@ -317,7 +323,7 @@ final class LocationAnimatorCoordinator {
createNewAnimator(ANIMATOR_CAMERA_LATLNG,
new CameraLatLngAnimator(previousCameraTarget, currentTarget, cameraListeners));
- return immediateAnimation(previousCameraTarget, currentTarget, currentCameraPosition.zoom);
+ return immediateAnimation(projection, previousCameraTarget, currentTarget);
}
private void resetCameraGpsBearingAnimation(@NonNull CameraPosition currentCameraPosition, boolean isGpsNorth) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java
index 0a876fb5cb..c237a7928f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationCameraController.java
@@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.view.MotionEvent;
+
import com.mapbox.android.gestures.AndroidGesturesManager;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.android.gestures.RotateGestureDetector;
@@ -128,7 +129,7 @@ final class LocationCameraController implements MapboxAnimator.OnCameraAnimation
};
CameraPosition currentPosition = mapboxMap.getCameraPosition();
- if (Utils.immediateAnimation(currentPosition.target, target, currentPosition.zoom)) {
+ if (Utils.immediateAnimation(mapboxMap.getProjection(), currentPosition.target, target)) {
mapboxMap.moveCamera(
update,
callback);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java
index 7e312a8158..42b8db212d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponent.java
@@ -993,7 +993,7 @@ public final class LocationComponent {
locationCameraController = new LocationCameraController(
context, mapboxMap, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener);
- locationAnimatorCoordinator = new LocationAnimatorCoordinator();
+ locationAnimatorCoordinator = new LocationAnimatorCoordinator(mapboxMap.getProjection());
locationAnimatorCoordinator.addLayerListener(locationLayerController);
locationAnimatorCoordinator.addCameraListener(locationCameraController);
locationAnimatorCoordinator.setTrackingAnimationDurationMultiplier(options
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java
index 29fe413a22..912141c627 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentConstants.java
@@ -24,7 +24,7 @@ final class LocationComponentConstants {
static final long DEFAULT_TRACKING_TILT_ANIM_DURATION = 1250;
// Threshold value to perform immediate camera/layer position update.
- static final double INSTANT_LOCATION_TRANSITION_THRESHOLD = 500_000;
+ static final double INSTANT_LOCATION_TRANSITION_THRESHOLD = 50_000;
// Default interval between location updates
static final long DEFAULT_INTERVAL_MILLIS = 1000;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java
index 7a2415ed5d..2e95da8ad5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/Utils.java
@@ -16,6 +16,7 @@ import android.support.v4.content.ContextCompat;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.Projection;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.INSTANT_LOCATION_TRANSITION_THRESHOLD;
@@ -92,13 +93,10 @@ public final class Utils {
return (float) (location.getAccuracy() * (1 / metersPerPixel));
}
- static boolean immediateAnimation(LatLng current, @NonNull LatLng target, double zoom) {
- // TODO: calculate the value based on the projection
+ static boolean immediateAnimation(@NonNull Projection projection, @NonNull LatLng current, @NonNull LatLng target) {
+ double metersPerPixel = projection.getMetersPerPixelAtLatitude((current.getLatitude() + target.getLatitude()) / 2);
double distance = current.distanceTo(target);
- if (zoom > 10) {
- distance *= zoom;
- }
- return distance > INSTANT_LOCATION_TRANSITION_THRESHOLD;
+ return distance / metersPerPixel > INSTANT_LOCATION_TRANSITION_THRESHOLD;
}
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinatorTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinatorTest.kt
index 2c94642610..fad71237ab 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinatorTest.kt
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationAnimatorCoordinatorTest.kt
@@ -6,12 +6,14 @@ import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_TRACKING_TILT_ANIM_DURATION
import com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_TRACKING_ZOOM_ANIM_DURATION
import com.mapbox.mapboxsdk.location.MapboxAnimator.*
+import com.mapbox.mapboxsdk.maps.Projection
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
+import org.mockito.Mockito.mock
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
@@ -22,7 +24,7 @@ class LocationAnimatorCoordinatorTest {
@Before
fun setUp() {
- locationAnimatorCoordinator = LocationAnimatorCoordinator()
+ locationAnimatorCoordinator = LocationAnimatorCoordinator(mock(Projection::class.java))
}
@Test
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java
index 4f950cebac..475426f77c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationCameraControllerTest.java
@@ -454,6 +454,9 @@ public class LocationCameraControllerTest {
public void transition_trackingChanged() {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getCameraPosition()).thenReturn(CameraPosition.DEFAULT);
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
LocationCameraController camera = buildCamera(mapboxMap);
camera.initializeOptions(mock(LocationComponentOptions.class));
final OnLocationCameraTransitionListener listener = mock(OnLocationCameraTransitionListener.class);
@@ -478,6 +481,9 @@ public class LocationCameraControllerTest {
public void transition_trackingNotChanged() {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getCameraPosition()).thenReturn(CameraPosition.DEFAULT);
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
LocationCameraController camera = buildCamera(mapboxMap);
camera.initializeOptions(mock(LocationComponentOptions.class));
final OnLocationCameraTransitionListener listener = mock(OnLocationCameraTransitionListener.class);
@@ -504,6 +510,9 @@ public class LocationCameraControllerTest {
public void transition_canceled() {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getCameraPosition()).thenReturn(CameraPosition.DEFAULT);
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
LocationCameraController camera = buildCamera(mapboxMap);
camera.initializeOptions(mock(LocationComponentOptions.class));
final OnLocationCameraTransitionListener listener = mock(OnLocationCameraTransitionListener.class);
@@ -528,6 +537,9 @@ public class LocationCameraControllerTest {
public void transition_mapboxCallbackFinished() {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getCameraPosition()).thenReturn(CameraPosition.DEFAULT);
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
LocationCameraController camera = buildCamera(mapboxMap);
camera.initializeOptions(mock(LocationComponentOptions.class));
final OnLocationCameraTransitionListener listener = mock(OnLocationCameraTransitionListener.class);
@@ -558,9 +570,47 @@ public class LocationCameraControllerTest {
}
@Test
+ public void transition_mapboxCallbackFinishedImmediately() {
+ MapboxMap mapboxMap = mock(MapboxMap.class);
+ when(mapboxMap.getCameraPosition()).thenReturn(CameraPosition.DEFAULT);
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1));
+ LocationCameraController camera = buildCamera(mapboxMap);
+ camera.initializeOptions(mock(LocationComponentOptions.class));
+ final OnLocationCameraTransitionListener listener = mock(OnLocationCameraTransitionListener.class);
+ Location location = mock(Location.class);
+ when(location.getLatitude()).thenReturn(1.0);
+ when(location.getLongitude()).thenReturn(1.0);
+ when(location.getBearing()).thenReturn(30f);
+ when(location.getAltitude()).thenReturn(0.0);
+
+ ArgumentCaptor<MapboxMap.CancelableCallback> callbackCaptor
+ = ArgumentCaptor.forClass(MapboxMap.CancelableCallback.class);
+
+ camera.setCameraMode(CameraMode.TRACKING, location, listener);
+
+ CameraPosition.Builder builder = new CameraPosition.Builder().target(new LatLng(location));
+ verify(mapboxMap).moveCamera(
+ eq(CameraUpdateFactory.newCameraPosition(builder.build())),
+ callbackCaptor.capture());
+
+ Assert.assertTrue(camera.isTransitioning());
+
+ callbackCaptor.getValue().onFinish();
+
+ Assert.assertFalse(camera.isTransitioning());
+
+ verify(listener).onLocationCameraTransitionFinished(CameraMode.TRACKING);
+ }
+
+ @Test
public void transition_mapboxCallbackCanceled() {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getCameraPosition()).thenReturn(CameraPosition.DEFAULT);
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
LocationCameraController camera = buildCamera(mapboxMap);
camera.initializeOptions(mock(LocationComponentOptions.class));
final OnLocationCameraTransitionListener listener = mock(OnLocationCameraTransitionListener.class);
@@ -594,6 +644,9 @@ public class LocationCameraControllerTest {
public void transition_mapboxAnimateBearing() {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getCameraPosition()).thenReturn(CameraPosition.DEFAULT);
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
LocationCameraController camera = buildCamera(mapboxMap);
camera.initializeOptions(mock(LocationComponentOptions.class));
final OnLocationCameraTransitionListener listener = mock(OnLocationCameraTransitionListener.class);
@@ -616,6 +669,9 @@ public class LocationCameraControllerTest {
public void transition_mapboxAnimateNorth() {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getCameraPosition()).thenReturn(CameraPosition.DEFAULT);
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
LocationCameraController camera = buildCamera(mapboxMap);
camera.initializeOptions(mock(LocationComponentOptions.class));
final OnLocationCameraTransitionListener listener = mock(OnLocationCameraTransitionListener.class);
@@ -638,6 +694,9 @@ public class LocationCameraControllerTest {
public void transition_animatorValuesDuringTransition() {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getCameraPosition()).thenReturn(CameraPosition.DEFAULT);
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
LocationCameraController camera = buildCamera(mapboxMap);
camera.initializeOptions(mock(LocationComponentOptions.class));
final OnLocationCameraTransitionListener listener = mock(OnLocationCameraTransitionListener.class);
@@ -674,6 +733,9 @@ public class LocationCameraControllerTest {
private LocationCameraController buildCamera(OnCameraTrackingChangedListener onCameraTrackingChangedListener) {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class));
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
MoveGestureDetector moveGestureDetector = mock(MoveGestureDetector.class);
OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = mock(OnCameraMoveInvalidateListener.class);
AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class);
@@ -685,6 +747,9 @@ public class LocationCameraControllerTest {
private LocationCameraController buildCamera(MoveGestureDetector moveGestureDetector) {
MapboxMap mapboxMap = mock(MapboxMap.class);
when(mapboxMap.getUiSettings()).thenReturn(mock(UiSettings.class));
+ Projection projection = mock(Projection.class);
+ when(mapboxMap.getProjection()).thenReturn(projection);
+ when(projection.getMetersPerPixelAtLatitude(any(Double.class))).thenReturn(Double.valueOf(1000));
OnCameraTrackingChangedListener onCameraTrackingChangedListener = mock(OnCameraTrackingChangedListener.class);
OnCameraMoveInvalidateListener onCameraMoveInvalidateListener = mock(OnCameraMoveInvalidateListener.class);
AndroidGesturesManager initialGesturesManager = mock(AndroidGesturesManager.class);