[android] break location camera tracking when a developer invoked animation starts

This commit is contained in:
Łukasz Paczos
2019-05-23 15:02:14 +02:00
committed by Łukasz Paczos
parent aa3a7cf02f
commit bc74a8ee0b
9 changed files with 319 additions and 119 deletions

View File

@@ -17,6 +17,7 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.modes.CameraMode;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Transform;
import java.util.HashSet;
import java.util.Set;
@@ -29,6 +30,7 @@ final class LocationCameraController {
private int cameraMode;
private final MapboxMap mapboxMap;
private final Transform transform;
private final OnCameraTrackingChangedListener internalCameraTrackingChangedListener;
private LocationComponentOptions options;
private boolean adjustFocalPoint;
@@ -44,10 +46,12 @@ final class LocationCameraController {
LocationCameraController(
Context context,
MapboxMap mapboxMap,
Transform transform,
OnCameraTrackingChangedListener internalCameraTrackingChangedListener,
@NonNull LocationComponentOptions options,
OnCameraMoveInvalidateListener onCameraMoveInvalidateListener) {
this.mapboxMap = mapboxMap;
this.transform = transform;
initialGesturesManager = mapboxMap.getGesturesManager();
internalGesturesManager = new LocationGesturesManager(context);
@@ -63,12 +67,14 @@ final class LocationCameraController {
// Package private for testing purposes
LocationCameraController(MapboxMap mapboxMap,
Transform transform,
MoveGestureDetector moveGestureDetector,
OnCameraTrackingChangedListener internalCameraTrackingChangedListener,
OnCameraMoveInvalidateListener onCameraMoveInvalidateListener,
AndroidGesturesManager initialGesturesManager,
AndroidGesturesManager internalGesturesManager) {
this.mapboxMap = mapboxMap;
this.transform = transform;
this.moveGestureDetector = moveGestureDetector;
this.internalCameraTrackingChangedListener = internalCameraTrackingChangedListener;
this.onCameraMoveInvalidateListener = onCameraMoveInvalidateListener;
@@ -157,11 +163,13 @@ final class LocationCameraController {
CameraPosition currentPosition = mapboxMap.getCameraPosition();
if (Utils.immediateAnimation(mapboxMap.getProjection(), currentPosition.target, target)) {
mapboxMap.moveCamera(
transform.moveCamera(
mapboxMap,
update,
callback);
} else {
mapboxMap.animateCamera(
transform.animateCamera(
mapboxMap,
update,
(int) transitionDuration,
callback);
@@ -182,7 +190,7 @@ final class LocationCameraController {
return;
}
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing));
transform.moveCamera(mapboxMap, CameraUpdateFactory.bearingTo(bearing), null);
onCameraMoveInvalidateListener.onInvalidateCameraMove();
}
@@ -191,7 +199,7 @@ final class LocationCameraController {
return;
}
mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
transform.moveCamera(mapboxMap, CameraUpdateFactory.newLatLng(latLng), null);
onCameraMoveInvalidateListener.onInvalidateCameraMove();
if (adjustFocalPoint) {
@@ -206,7 +214,7 @@ final class LocationCameraController {
return;
}
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(zoom));
transform.moveCamera(mapboxMap, CameraUpdateFactory.zoomTo(zoom), null);
onCameraMoveInvalidateListener.onInvalidateCameraMove();
}
@@ -215,7 +223,7 @@ final class LocationCameraController {
return;
}
mapboxMap.moveCamera(CameraUpdateFactory.tiltTo(tilt));
transform.moveCamera(mapboxMap, CameraUpdateFactory.tiltTo(tilt), null);
onCameraMoveInvalidateListener.onInvalidateCameraMove();
}

View File

@@ -31,9 +31,11 @@ import com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraIdleListener;
import com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveListener;
import com.mapbox.mapboxsdk.maps.MapboxMap.OnMapClickListener;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.maps.Transform;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -96,6 +98,8 @@ public final class LocationComponent {
@NonNull
private final MapboxMap mapboxMap;
@NonNull
private final Transform transform;
private Style style;
private LocationComponentOptions options;
@NonNull
@@ -179,19 +183,26 @@ public final class LocationComponent {
* <p>
* To get the component object use {@link MapboxMap#getLocationComponent()}.
*/
public LocationComponent(@NonNull MapboxMap mapboxMap) {
public LocationComponent(@NonNull MapboxMap mapboxMap,
@NonNull Transform transform,
@NonNull List<MapboxMap.OnDeveloperAnimationListener> developerAnimationListeners) {
this.mapboxMap = mapboxMap;
this.transform = transform;
developerAnimationListeners.add(developerAnimationListener);
}
// used for creating a spy
LocationComponent() {
//noinspection ConstantConditions
mapboxMap = null;
transform = null;
}
@VisibleForTesting
LocationComponent(@NonNull MapboxMap mapboxMap,
@NonNull LocationEngineCallback<LocationEngineResult> currentlistener,
@NonNull Transform transform,
@NonNull List<MapboxMap.OnDeveloperAnimationListener> developerAnimationListeners,
@NonNull LocationEngineCallback<LocationEngineResult> currentListener,
@NonNull LocationEngineCallback<LocationEngineResult> lastListener,
@NonNull LocationLayerController locationLayerController,
@NonNull LocationCameraController locationCameraController,
@@ -200,7 +211,9 @@ public final class LocationComponent {
@NonNull CompassEngine compassEngine,
@NonNull InternalLocationEngineProvider internalLocationEngineProvider) {
this.mapboxMap = mapboxMap;
this.currentLocationEngineListener = currentlistener;
this.transform = transform;
developerAnimationListeners.add(developerAnimationListener);
this.currentLocationEngineListener = currentListener;
this.lastLocationEngineListener = lastListener;
this.locationLayerController = locationLayerController;
this.locationCameraController = locationCameraController;
@@ -1204,7 +1217,7 @@ public final class LocationComponent {
locationLayerController = new LocationLayerController(mapboxMap, style, sourceProvider, featureProvider,
bitmapProvider, options, renderModeChangedListener);
locationCameraController = new LocationCameraController(
context, mapboxMap, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener);
context, mapboxMap, transform, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener);
locationAnimatorCoordinator = new LocationAnimatorCoordinator(
mapboxMap.getProjection(),
@@ -1535,6 +1548,17 @@ public final class LocationComponent {
}
};
@NonNull
private final MapboxMap.OnDeveloperAnimationListener developerAnimationListener =
new MapboxMap.OnDeveloperAnimationListener() {
@Override
public void onDeveloperAnimationStarted() {
if (isComponentInitialized && isEnabled) {
setCameraMode(CameraMode.NONE);
}
}
};
static class InternalLocationEngineProvider {
LocationEngine getBestLocationEngine(@NonNull Context context, boolean background) {
return LocationEngineProvider.getBestLocationEngine(context, background);

View File

@@ -169,7 +169,9 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
Transform transform = new Transform(this, nativeMapView, cameraDispatcher);
// MapboxMap
mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, proj, registerTouchListener, cameraDispatcher);
List<MapboxMap.OnDeveloperAnimationListener> developerAnimationListeners = new ArrayList<>();
mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, proj, registerTouchListener, cameraDispatcher,
developerAnimationListeners);
mapboxMap.injectAnnotationManager(annotationManager);
// user input
@@ -182,7 +184,7 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
compassView.setOnClickListener(createCompassClickListener(cameraDispatcher));
// LocationComponent
mapboxMap.injectLocationComponent(new LocationComponent(mapboxMap));
mapboxMap.injectLocationComponent(new LocationComponent(mapboxMap, transform, developerAnimationListeners));
// inject widgets with MapboxMap
attrView.setOnClickListener(attributionClickListener = new AttributionClickListener(context, mapboxMap));

View File

@@ -12,6 +12,7 @@ import android.support.annotation.Size;
import android.support.annotation.UiThread;
import android.text.TextUtils;
import android.view.View;
import com.mapbox.android.gestures.AndroidGesturesManager;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.android.gestures.RotateGestureDetector;
@@ -63,6 +64,7 @@ public final class MapboxMap {
private final CameraChangeDispatcher cameraChangeDispatcher;
private final OnGesturesManagerInteractionListener onGesturesManagerInteractionListener;
private final List<Style.OnStyleLoaded> awaitingStyleGetters = new ArrayList<>();
private final List<OnDeveloperAnimationListener> developerAnimationStartedListeners;
@Nullable
private Style.OnStyleLoaded styleLoadedCallback;
@@ -79,13 +81,15 @@ public final class MapboxMap {
private boolean debugActive;
MapboxMap(NativeMap map, Transform transform, UiSettings ui, Projection projection,
OnGesturesManagerInteractionListener listener, CameraChangeDispatcher cameraChangeDispatcher) {
OnGesturesManagerInteractionListener listener, CameraChangeDispatcher cameraChangeDispatcher,
List<OnDeveloperAnimationListener> developerAnimationStartedListeners) {
this.nativeMapView = map;
this.uiSettings = ui;
this.projection = projection;
this.transform = transform;
this.onGesturesManagerInteractionListener = listener;
this.cameraChangeDispatcher = cameraChangeDispatcher;
this.developerAnimationStartedListeners = developerAnimationStartedListeners;
}
void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) {
@@ -414,6 +418,7 @@ public final class MapboxMap {
*/
public final void moveCamera(@NonNull final CameraUpdate update,
@Nullable final MapboxMap.CancelableCallback callback) {
notifyDeveloperAnimationListeners();
transform.moveCamera(MapboxMap.this, update, callback);
}
@@ -522,10 +527,10 @@ public final class MapboxMap {
final int durationMs,
final boolean easingInterpolator,
@Nullable final MapboxMap.CancelableCallback callback) {
if (durationMs <= 0) {
throw new IllegalArgumentException("Null duration passed into easeCamera");
}
notifyDeveloperAnimationListeners();
transform.easeCamera(MapboxMap.this, update, durationMs, easingInterpolator, callback);
}
@@ -596,7 +601,7 @@ public final class MapboxMap {
if (durationMs <= 0) {
throw new IllegalArgumentException("Null duration passed into animateCamera");
}
notifyDeveloperAnimationListeners();
transform.animateCamera(MapboxMap.this, update, durationMs, callback);
}
@@ -608,7 +613,7 @@ public final class MapboxMap {
* @param y Amount of pixels to scroll to in y direction
*/
public void scrollBy(float x, float y) {
nativeMapView.moveBy(x, y, 0);
scrollBy(x, y, 0);
}
/**
@@ -620,6 +625,7 @@ public final class MapboxMap {
* @param duration Amount of time the scrolling should take
*/
public void scrollBy(float x, float y, long duration) {
notifyDeveloperAnimationListeners();
nativeMapView.moveBy(x, y, duration);
}
@@ -631,6 +637,7 @@ public final class MapboxMap {
* Resets the map view to face north.
*/
public void resetNorth() {
notifyDeveloperAnimationListeners();
transform.resetNorth();
}
@@ -643,6 +650,7 @@ public final class MapboxMap {
* @param duration The duration of the transformation
*/
public void setFocalBearing(double bearing, float focalX, float focalY, long duration) {
notifyDeveloperAnimationListeners();
transform.setBearing(bearing, focalX, focalY, duration);
}
@@ -2342,6 +2350,17 @@ public final class MapboxMap {
void onSnapshotReady(@NonNull Bitmap snapshot);
}
/**
* Internal use.
*/
public interface OnDeveloperAnimationListener {
/**
* Notifies listener when a developer invoked animation is about to start.
*/
void onDeveloperAnimationStarted();
}
//
// Used for instrumentation testing
//
@@ -2349,4 +2368,10 @@ public final class MapboxMap {
Transform getTransform() {
return transform;
}
private void notifyDeveloperAnimationListeners() {
for (OnDeveloperAnimationListener listener : developerAnimationStartedListeners) {
listener.onDeveloperAnimationStarted();
}
}
}

View File

@@ -16,12 +16,15 @@ import com.mapbox.mapboxsdk.log.Logger;
import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener;
/**
* Internal use.
* <p>
* Resembles the current Map transformation.
* </p>
* <p>
* Responsible for synchronising {@link CameraPosition} state and notifying camera change listeners.
* </p>
*/
final class Transform implements MapView.OnCameraDidChangeListener {
public final class Transform implements MapView.OnCameraDidChangeListener {
private static final String TAG = "Mbgl-Transform";
@@ -95,9 +98,12 @@ final class Transform implements MapView.OnCameraDidChangeListener {
}
}
/**
* Internal use.
*/
@UiThread
final void moveCamera(@NonNull MapboxMap mapboxMap, CameraUpdate update,
@Nullable final MapboxMap.CancelableCallback callback) {
public final void moveCamera(@NonNull MapboxMap mapboxMap, CameraUpdate update,
@Nullable final MapboxMap.CancelableCallback callback) {
CameraPosition cameraPosition = update.getCameraPosition(mapboxMap);
if (isValidCameraPosition(cameraPosition)) {
cancelTransitions();
@@ -133,9 +139,12 @@ final class Transform implements MapView.OnCameraDidChangeListener {
}
}
/**
* Internal use.
*/
@UiThread
final void animateCamera(@NonNull MapboxMap mapboxMap, CameraUpdate update, int durationMs,
@Nullable final MapboxMap.CancelableCallback callback) {
public final void animateCamera(@NonNull MapboxMap mapboxMap, CameraUpdate update, int durationMs,
@Nullable final MapboxMap.CancelableCallback callback) {
CameraPosition cameraPosition = update.getCameraPosition(mapboxMap);
if (isValidCameraPosition(cameraPosition)) {
cancelTransitions();