From a39cf73ee377d5b0d2508803d129afdf6e5a78aa Mon Sep 17 00:00:00 2001 From: danesfeder Date: Thu, 28 Mar 2019 11:48:39 -0400 Subject: [PATCH] Add NavigationCamera#update for MapboxMap animations --- .../ComponentNavigationActivity.java | 21 ++++- .../navigation/ui/v5/NavigationContract.java | 3 - .../navigation/ui/v5/NavigationPresenter.java | 2 - .../navigation/ui/v5/NavigationView.java | 8 -- .../ui/v5/camera/CameraAnimationDelegate.java | 30 +++++++ .../ui/v5/camera/CameraUpdateMode.java | 24 ++++++ .../ui/v5/camera/NavigationCamera.java | 86 ++++++++++++++++--- ...vigationCameraTrackingChangedListener.java | 25 ++++++ .../ui/v5/camera/NavigationCameraUpdate.java | 48 +++++++++++ .../ui/v5/camera/NavigationCameraTest.java | 71 +++++++++++++++ ...tionCameraTrackingChangedListenerTest.java | 34 ++++++++ 11 files changed, 325 insertions(+), 27 deletions(-) create mode 100644 libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/CameraAnimationDelegate.java create mode 100644 libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/CameraUpdateMode.java create mode 100644 libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTrackingChangedListener.java create mode 100644 libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraUpdate.java create mode 100644 libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTrackingChangedListenerTest.java diff --git a/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/ComponentNavigationActivity.java b/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/ComponentNavigationActivity.java index 924032ad232..aea32cfbc41 100644 --- a/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/ComponentNavigationActivity.java +++ b/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/ComponentNavigationActivity.java @@ -9,6 +9,7 @@ import android.os.VibrationEffect; import android.os.Vibrator; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.constraint.ConstraintLayout; import android.support.design.widget.BaseTransientBottomBar; import android.support.design.widget.FloatingActionButton; @@ -26,6 +27,7 @@ import com.mapbox.geojson.Point; import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.camera.CameraUpdate; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; @@ -38,6 +40,7 @@ import com.mapbox.services.android.navigation.testapp.activity.HistoryActivity; import com.mapbox.services.android.navigation.ui.v5.camera.DynamicCamera; import com.mapbox.services.android.navigation.ui.v5.camera.NavigationCamera; +import com.mapbox.services.android.navigation.ui.v5.camera.NavigationCameraUpdate; import com.mapbox.services.android.navigation.ui.v5.instruction.InstructionView; import com.mapbox.services.android.navigation.ui.v5.map.NavigationMapboxMap; import com.mapbox.services.android.navigation.ui.v5.voice.NavigationSpeechPlayer; @@ -171,7 +174,6 @@ public boolean onMapLongClick(@NonNull LatLng point) { @OnClick(R.id.startNavigationFab) public void onStartNavigationClick(FloatingActionButton floatingActionButton) { - navigationMap.updateCameraTrackingMode(NavigationCamera.NAVIGATION_TRACKING_MODE_GPS); // Transition to navigation state mapState = MapState.NAVIGATION; @@ -188,6 +190,14 @@ public void onStartNavigationClick(FloatingActionButton floatingActionButton) { // Location updates will be received from ProgressChangeListener removeLocationEngineListener(); + + // TODO remove example usage + navigationMap.resetCameraPositionWith(NavigationCamera.NAVIGATION_TRACKING_MODE_GPS); + CameraUpdate cameraUpdate = cameraOverheadUpdate(); + if (cameraUpdate != null) { + NavigationCameraUpdate navUpdate = new NavigationCameraUpdate(cameraUpdate); + navigationMap.retrieveCamera().update(navUpdate); + } } @OnClick(R.id.cancelNavigationFab) @@ -388,6 +398,15 @@ private void moveCameraOverhead() { ); } + @Nullable + private CameraUpdate cameraOverheadUpdate() { + if (lastLocation == null) { + return null; + } + CameraPosition cameraPosition = buildCameraPositionFrom(lastLocation, DEFAULT_BEARING); + return CameraUpdateFactory.newCameraPosition(cameraPosition); + } + @NonNull private CameraPosition buildCameraPositionFrom(Location location, double bearing) { return new CameraPosition.Builder() diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationContract.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationContract.java index f7428cd3db6..a58844d8985 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationContract.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationContract.java @@ -5,7 +5,6 @@ import com.mapbox.api.directions.v5.models.DirectionsRoute; import com.mapbox.geojson.Point; -import com.mapbox.services.android.navigation.ui.v5.camera.NavigationCamera; public interface NavigationContract { @@ -21,8 +20,6 @@ interface View { void updateWayNameView(@NonNull String wayName); - void updateCameraTrackingMode(@NavigationCamera.TrackingMode int trackingMode); - void resetCameraPosition(); void showRecenterBtn(); diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationPresenter.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationPresenter.java index b88b31c074e..7aeeb5d4efb 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationPresenter.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationPresenter.java @@ -7,7 +7,6 @@ import com.mapbox.api.directions.v5.models.DirectionsRoute; import com.mapbox.core.utils.TextUtils; import com.mapbox.geojson.Point; -import com.mapbox.services.android.navigation.ui.v5.camera.NavigationCamera; class NavigationPresenter { @@ -34,7 +33,6 @@ void onCameraTrackingDismissed() { if (!view.isSummaryBottomSheetHidden()) { view.setSummaryBehaviorHideable(true); view.setSummaryBehaviorState(BottomSheetBehavior.STATE_HIDDEN); - view.updateCameraTrackingMode(NavigationCamera.NAVIGATION_TRACKING_MODE_NONE); view.updateWayNameVisibility(false); } } diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationView.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationView.java index 6560d6752cb..87e09306a76 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationView.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationView.java @@ -243,14 +243,6 @@ public boolean isSummaryBottomSheetHidden() { return summaryBehavior.getState() == BottomSheetBehavior.STATE_HIDDEN; } - - @Override - public void updateCameraTrackingMode(int trackingMode) { - if (navigationMap != null) { - navigationMap.updateCameraTrackingMode(trackingMode); - } - } - @Override public void resetCameraPosition() { if (navigationMap != null) { diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/CameraAnimationDelegate.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/CameraAnimationDelegate.java new file mode 100644 index 00000000000..fafa56e62c5 --- /dev/null +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/CameraAnimationDelegate.java @@ -0,0 +1,30 @@ +package com.mapbox.services.android.navigation.ui.v5.camera; + +import com.mapbox.mapboxsdk.camera.CameraUpdate; +import com.mapbox.mapboxsdk.location.modes.CameraMode; +import com.mapbox.mapboxsdk.maps.MapboxMap; + +class CameraAnimationDelegate { + + private final MapboxMap mapboxMap; + + CameraAnimationDelegate(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + } + + void render(NavigationCameraUpdate update, int durationMs, MapboxMap.CancelableCallback callback) { + CameraUpdateMode mode = update.getMode(); + CameraUpdate cameraUpdate = update.getCameraUpdate(); + if (mode == CameraUpdateMode.OVERRIDE) { + mapboxMap.getLocationComponent().setCameraMode(CameraMode.NONE); + mapboxMap.animateCamera(cameraUpdate, durationMs, callback); + } else if (!isTracking()) { + mapboxMap.animateCamera(cameraUpdate, durationMs, callback); + } + } + + private boolean isTracking() { + int cameraMode = mapboxMap.getLocationComponent().getCameraMode(); + return cameraMode != CameraMode.NONE; + } +} \ No newline at end of file diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/CameraUpdateMode.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/CameraUpdateMode.java new file mode 100644 index 00000000000..3b176d9df6a --- /dev/null +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/CameraUpdateMode.java @@ -0,0 +1,24 @@ +package com.mapbox.services.android.navigation.ui.v5.camera; + +/** + * This class is passed to {@link NavigationCameraUpdate} to + * determine the update's behavior when passed to {@link NavigationCamera}. + */ +public enum CameraUpdateMode { + + /** + * For a given {@link NavigationCameraUpdate}, this default mode means the + * {@link NavigationCamera} will ignore the update when tracking is already + * enabled. + *

+ * If tracking is disabled, the update animation will execute. + */ + DEFAULT, + + /** + * For a given {@link NavigationCameraUpdate}, this override mode means the + * {@link NavigationCamera} will stop tracking (if tracking) and execute the + * given update animation. + */ + OVERRIDE +} \ No newline at end of file diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCamera.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCamera.java index 98b8afdfb3f..6e3fd618ea2 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCamera.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCamera.java @@ -14,9 +14,11 @@ import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.camera.CameraUpdate; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; +import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; import com.mapbox.mapboxsdk.location.LocationComponent; +import com.mapbox.mapboxsdk.location.OnCameraTrackingChangedListener; import com.mapbox.mapboxsdk.location.OnLocationCameraTransitionListener; import com.mapbox.mapboxsdk.location.modes.CameraMode; import com.mapbox.mapboxsdk.maps.MapboxMap; @@ -74,6 +76,8 @@ public class NavigationCamera implements LifecycleObserver { = new CopyOnWriteArrayList<>(); private final OnLocationCameraTransitionListener cameraTransitionListener = new NavigationCameraTransitionListener(this); + private final OnCameraTrackingChangedListener cameraTrackingChangedListener + = new NavigationCameraTrackingChangedListener(this); private MapboxMap mapboxMap; private LocationComponent locationComponent; private MapboxNavigation navigation; @@ -82,6 +86,7 @@ public class NavigationCamera implements LifecycleObserver { @TrackingMode private int trackingCameraMode = NAVIGATION_TRACKING_MODE_GPS; private boolean isCameraResetting; + private CameraAnimationDelegate animationDelegate; private ProgressChangeListener progressChangeListener = new ProgressChangeListener() { @Override public void onProgressChange(Location location, RouteProgress routeProgress) { @@ -107,6 +112,8 @@ public NavigationCamera(@NonNull MapboxMap mapboxMap, @NonNull MapboxNavigation this.mapboxMap = mapboxMap; this.navigation = navigation; this.locationComponent = locationComponent; + this.animationDelegate = new CameraAnimationDelegate(mapboxMap); + this.locationComponent.addOnCameraTrackingChangedListener(cameraTrackingChangedListener); initializeWith(navigation); } @@ -121,6 +128,8 @@ public NavigationCamera(@NonNull MapboxMap mapboxMap, @NonNull MapboxNavigation public NavigationCamera(@NonNull MapboxMap mapboxMap, LocationComponent locationComponent) { this.mapboxMap = mapboxMap; this.locationComponent = locationComponent; + this.animationDelegate = new CameraAnimationDelegate(mapboxMap); + this.locationComponent.addOnCameraTrackingChangedListener(cameraTrackingChangedListener); updateCameraTrackingMode(trackingCameraMode); } @@ -212,6 +221,57 @@ public void showRouteOverview(int[] padding) { animateCameraForRouteOverview(routeInformation, padding); } + /** + * Animate the camera to a new location defined within {@link CameraUpdate} passed to the + * {@link NavigationCameraUpdate} using a transition animation that evokes powered flight. + * If the camera is in a tracking mode, this animation is going to be ignored, or break the tracking, + * based on the {@link CameraUpdateMode). + * + * @param update the change that should be applied to the camera. + * @see CameraUpdateMode for how this update interacts with the current tracking + */ + public void update(NavigationCameraUpdate update) { + animationDelegate.render(update, MapboxConstants.ANIMATION_DURATION, null); + } + + /** + * Animate the camera to a new location defined within {@link CameraUpdate} passed to the + * {@link NavigationCameraUpdate} using a transition animation that evokes powered flight. + * The animation will last a specified amount of time given in milliseconds. If the camera is in a tracking mode, + * this animation is going to be ignored, or break the tracking, based on the {@link CameraUpdateMode). + * + * @param update the change that should be applied to the camera. + * @param durationMs the duration of the animation in milliseconds. This must be strictly + * positive, otherwise an IllegalArgumentException will be thrown. + * @see CameraUpdateMode for how this update interacts with the current tracking + */ + public void update(NavigationCameraUpdate update, int durationMs) { + animationDelegate.render(update, durationMs, null); + } + + /** + * Animate the camera to a new location defined within {@link CameraUpdate} passed to the + * {@link NavigationCameraUpdate} using a transition animation that evokes powered flight. The animation will + * last a specified amount of time given in milliseconds. A callback can be used to be notified when animating + * the camera stops. During the animation, a call to {@link MapboxMap#getCameraPosition()} returns an intermediate + * location of the camera in flight. If the camera is in a tracking mode, + * this animation is going to be ignored, or break the tracking, based on the {@link CameraUpdateMode). + * + * @param update the change that should be applied to the camera. + * @param durationMs the duration of the animation in milliseconds. This must be strictly + * positive, otherwise an IllegalArgumentException will be thrown. + * @param callback an optional callback to be notified from the main thread when the animation + * stops. If the animation stops due to its natural completion, the callback + * will be notified with onFinish(). If the animation stops due to interruption + * by a later camera movement or a user gesture, onCancel() will be called. + * Do not update or animate the camera from within onCancel(). If a callback + * isn't required, leave it as null. + * @see CameraUpdateMode for how this update interacts with the current tracking + */ + public void update(NavigationCameraUpdate update, int durationMs, @Nullable MapboxMap.CancelableCallback callback) { + animationDelegate.render(update, durationMs, callback); + } + /** * Call in {@link FragmentActivity#onStart()} to properly add the {@link ProgressChangeListener} * for the camera and prevent any leaks or further updates. @@ -309,6 +369,19 @@ void updateTransitionListenersCancelled(@CameraMode.Mode int cameraMode) { } } + @Nullable + Integer findTrackingModeFor(@CameraMode.Mode int cameraMode) { + if (cameraMode == CameraMode.TRACKING_GPS) { + return NAVIGATION_TRACKING_MODE_GPS; + } else if (cameraMode == CameraMode.TRACKING_GPS_NORTH) { + return NAVIGATION_TRACKING_MODE_NORTH; + } else if (cameraMode == CameraMode.NONE) { + return NAVIGATION_TRACKING_MODE_NONE; + } else { + return null; + } + } + void updateIsResetting(boolean isResetting) { this.isCameraResetting = isResetting; } @@ -429,19 +502,6 @@ private Integer findCameraModeFor(@TrackingMode int trackingCameraMode) { } } - @Nullable - private Integer findTrackingModeFor(@CameraMode.Mode int cameraMode) { - if (cameraMode == CameraMode.TRACKING_GPS) { - return NAVIGATION_TRACKING_MODE_GPS; - } else if (cameraMode == CameraMode.TRACKING_GPS_NORTH) { - return NAVIGATION_TRACKING_MODE_NORTH; - } else if (cameraMode == CameraMode.NONE) { - return NAVIGATION_TRACKING_MODE_NONE; - } else { - return null; - } - } - private void updateTrackingModeListenersWith(@TrackingMode int trackingMode) { for (OnTrackingModeChangedListener listener : onTrackingModeChangedListeners) { listener.onTrackingModeChanged(trackingMode); diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTrackingChangedListener.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTrackingChangedListener.java new file mode 100644 index 00000000000..4c864547e58 --- /dev/null +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTrackingChangedListener.java @@ -0,0 +1,25 @@ +package com.mapbox.services.android.navigation.ui.v5.camera; + +import com.mapbox.mapboxsdk.location.OnCameraTrackingChangedListener; + +class NavigationCameraTrackingChangedListener implements OnCameraTrackingChangedListener { + + private final NavigationCamera camera; + + NavigationCameraTrackingChangedListener(NavigationCamera camera) { + this.camera = camera; + } + + @Override + public void onCameraTrackingDismissed() { + camera.updateCameraTrackingMode(NavigationCamera.NAVIGATION_TRACKING_MODE_NONE); + } + + @Override + public void onCameraTrackingChanged(int currentMode) { + Integer trackingMode = camera.findTrackingModeFor(currentMode); + if (trackingMode != null) { + camera.updateCameraTrackingMode(trackingMode); + } + } +} \ No newline at end of file diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraUpdate.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraUpdate.java new file mode 100644 index 00000000000..be5ac72050c --- /dev/null +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraUpdate.java @@ -0,0 +1,48 @@ +package com.mapbox.services.android.navigation.ui.v5.camera; + +import android.support.annotation.NonNull; + +import com.mapbox.mapboxsdk.camera.CameraUpdate; + +/** + * Used with {@link NavigationCamera#update(NavigationCameraUpdate)}. + *

+ * This class wraps a Maps SDK {@link CameraUpdate}. It adds an option + * for {@link CameraUpdateMode} that determine how the camera update behaves + * with tracking modes. + */ +public class NavigationCameraUpdate { + + private final CameraUpdate cameraUpdate; + private CameraUpdateMode mode = CameraUpdateMode.DEFAULT; + + /** + * Creates and instance of this class, taking a {@link CameraUpdate} + * that has already been built. + * + * @param cameraUpdate with map camera parameters + */ + public NavigationCameraUpdate(@NonNull CameraUpdate cameraUpdate) { + this.cameraUpdate = cameraUpdate; + } + + /** + * Updates the {@link CameraUpdateMode} that will determine this updates + * behavior based on the current tracking mode in {@link NavigationCamera}. + * + * @param mode either default or override + */ + public void setMode(CameraUpdateMode mode) { + this.mode = mode; + } + + @NonNull + CameraUpdate getCameraUpdate() { + return cameraUpdate; + } + + @NonNull + CameraUpdateMode getMode() { + return mode; + } +} \ No newline at end of file diff --git a/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTest.java b/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTest.java index 7b65a772066..8de0ac99fc2 100644 --- a/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTest.java +++ b/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTest.java @@ -1,6 +1,7 @@ package com.mapbox.services.android.navigation.ui.v5.camera; import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.camera.CameraUpdate; import com.mapbox.mapboxsdk.location.LocationComponent; import com.mapbox.mapboxsdk.location.OnLocationCameraTransitionListener; import com.mapbox.mapboxsdk.location.modes.CameraMode; @@ -120,10 +121,80 @@ public void onResumeWithNullLocation_progressListenerIsAdded() { verify(navigation, times(1)).addProgressChangeListener(listener); } + @Test + public void update_defaultIsIgnoredWhileTracking() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationComponent locationComponent = mock(LocationComponent.class); + when(locationComponent.getCameraMode()).thenReturn(CameraMode.TRACKING_GPS); + when(mapboxMap.getLocationComponent()).thenReturn(locationComponent); + CameraUpdate cameraUpdate = mock(CameraUpdate.class); + MapboxMap.CancelableCallback callback = mock(MapboxMap.CancelableCallback.class); + NavigationCameraUpdate navigationCameraUpdate = new NavigationCameraUpdate(cameraUpdate); + NavigationCamera camera = buildCamera(mapboxMap); + + camera.update(navigationCameraUpdate, 300, callback); + + verify(mapboxMap, times(0)).animateCamera(cameraUpdate); + } + + @Test + public void update_defaultIsAcceptedWithNoTracking() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationComponent locationComponent = mock(LocationComponent.class); + when(locationComponent.getCameraMode()).thenReturn(CameraMode.NONE); + when(mapboxMap.getLocationComponent()).thenReturn(locationComponent); + CameraUpdate cameraUpdate = mock(CameraUpdate.class); + MapboxMap.CancelableCallback callback = mock(MapboxMap.CancelableCallback.class); + NavigationCameraUpdate navigationCameraUpdate = new NavigationCameraUpdate(cameraUpdate); + NavigationCamera camera = buildCamera(mapboxMap); + + camera.update(navigationCameraUpdate, 300, callback); + + verify(mapboxMap).animateCamera(eq(cameraUpdate), eq(300), eq(callback)); + } + + @Test + public void update_overrideIsAcceptedWhileTracking() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationComponent locationComponent = mock(LocationComponent.class); + when(locationComponent.getCameraMode()).thenReturn(CameraMode.TRACKING_GPS); + when(mapboxMap.getLocationComponent()).thenReturn(locationComponent); + CameraUpdate cameraUpdate = mock(CameraUpdate.class); + MapboxMap.CancelableCallback callback = mock(MapboxMap.CancelableCallback.class); + NavigationCameraUpdate navigationCameraUpdate = new NavigationCameraUpdate(cameraUpdate); + navigationCameraUpdate.setMode(CameraUpdateMode.OVERRIDE); + NavigationCamera camera = buildCamera(mapboxMap); + + camera.update(navigationCameraUpdate, 300, callback); + + verify(mapboxMap).animateCamera(eq(cameraUpdate), eq(300), eq(callback)); + } + + @Test + public void update_overrideSetsLocationComponentCameraModeNone() { + MapboxMap mapboxMap = mock(MapboxMap.class); + LocationComponent locationComponent = mock(LocationComponent.class); + when(locationComponent.getCameraMode()).thenReturn(CameraMode.TRACKING_GPS); + when(mapboxMap.getLocationComponent()).thenReturn(locationComponent); + CameraUpdate cameraUpdate = mock(CameraUpdate.class); + MapboxMap.CancelableCallback callback = mock(MapboxMap.CancelableCallback.class); + NavigationCameraUpdate navigationCameraUpdate = new NavigationCameraUpdate(cameraUpdate); + navigationCameraUpdate.setMode(CameraUpdateMode.OVERRIDE); + NavigationCamera camera = buildCamera(mapboxMap); + + camera.update(navigationCameraUpdate, 300, callback); + + verify(locationComponent).setCameraMode(eq(CameraMode.NONE)); + } + private NavigationCamera buildCamera() { return new NavigationCamera(mock(MapboxMap.class), mock(MapboxNavigation.class), mock(LocationComponent.class)); } + private NavigationCamera buildCamera(MapboxMap mapboxMap) { + return new NavigationCamera(mapboxMap, mock(MapboxNavigation.class), mock(LocationComponent.class)); + } + private NavigationCamera buildCamera(LocationComponent locationComponent) { return new NavigationCamera(mock(MapboxMap.class), mock(MapboxNavigation.class), locationComponent); } diff --git a/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTrackingChangedListenerTest.java b/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTrackingChangedListenerTest.java new file mode 100644 index 00000000000..ef85b364285 --- /dev/null +++ b/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/camera/NavigationCameraTrackingChangedListenerTest.java @@ -0,0 +1,34 @@ +package com.mapbox.services.android.navigation.ui.v5.camera; + +import com.mapbox.mapboxsdk.location.modes.CameraMode; + +import org.junit.Test; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class NavigationCameraTrackingChangedListenerTest { + + @Test + public void onCameraTrackingDismissed_cameraSetToTrackingNone() { + NavigationCamera camera = mock(NavigationCamera.class); + NavigationCameraTrackingChangedListener listener = new NavigationCameraTrackingChangedListener(camera); + + listener.onCameraTrackingDismissed(); + + verify(camera).updateCameraTrackingMode(eq(NavigationCamera.NAVIGATION_TRACKING_MODE_NONE)); + } + + @Test + public void onCameraTrackingChanged_navigationCameraTrackingUpdated() { + NavigationCamera camera = mock(NavigationCamera.class); + when(camera.findTrackingModeFor(CameraMode.TRACKING_GPS)).thenReturn(NavigationCamera.NAVIGATION_TRACKING_MODE_GPS); + NavigationCameraTrackingChangedListener listener = new NavigationCameraTrackingChangedListener(camera); + + listener.onCameraTrackingChanged(CameraMode.TRACKING_GPS); + + verify(camera).updateCameraTrackingMode(eq(NavigationCamera.NAVIGATION_TRACKING_MODE_GPS)); + } +} \ No newline at end of file