Skip to content

Commit

Permalink
Add tracking with padding to Android 10.3.0 release (#2194)
Browse files Browse the repository at this point in the history
  • Loading branch information
louwers authored Mar 13, 2024
1 parent c09fc51 commit acee2d4
Show file tree
Hide file tree
Showing 17 changed files with 452 additions and 87 deletions.
1 change: 1 addition & 0 deletions platform/android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ MapLibre welcomes participation and contributions from everyone. Please read [`C
* Add support for the [`slice` expression](https://maplibre.org/maplibre-style-spec/expressions/#slice) ([#1133](https://github.com/maplibre/maplibre-native/pull/1133))
* Add support for [index-of expression](https://maplibre.org/maplibre-style-spec/expressions/#index-of) ([#1113](https://github.com/maplibre/maplibre-native/pull/1113))
* Change to a more natural fling animation and allow setting `flingThreshold` and `flingAnimationBaseTime` in `UiSettings` ([#963](https://github.com/maplibre/maplibre-native/pull/963))
* Add setting padding when camera is tracking ([#2165](https://github.com/maplibre/maplibre-native/pull/2165)).

### 🐞 Bug fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_COMPASS_BEARING;
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_GPS_BEARING;
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_LAYER_LATLNG;
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_PADDING;
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_PULSING_CIRCLE;
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_TILT;
import static com.mapbox.mapboxsdk.location.MapboxAnimator.ANIMATOR_ZOOM;
Expand Down Expand Up @@ -216,6 +217,12 @@ void feedNewZoomLevel(double targetZoomLevel, @NonNull CameraPosition currentCam
playAnimators(animationDuration, ANIMATOR_ZOOM);
}

void feedNewPadding(double[] padding, @NonNull CameraPosition currentCameraPosition, long animationDuration,
@Nullable MapboxMap.CancelableCallback callback) {
updatePaddingAnimator(padding, currentCameraPosition.padding, callback);
playAnimators(animationDuration, ANIMATOR_PADDING);
}

void feedNewTilt(double targetTilt, @NonNull CameraPosition currentCameraPosition, long animationDuration,
@Nullable MapboxMap.CancelableCallback callback) {
updateTiltAnimator((float) targetTilt, (float) currentCameraPosition.tilt, callback);
Expand Down Expand Up @@ -316,6 +323,11 @@ private void updateZoomAnimator(float targetZoomLevel, float previousZoomLevel,
createNewCameraAdapterAnimator(ANIMATOR_ZOOM, new Float[] {previousZoomLevel, targetZoomLevel}, cancelableCallback);
}

private void updatePaddingAnimator(double[] targetPadding, double[] previousPadding,
@Nullable MapboxMap.CancelableCallback cancelableCallback) {
createNewPaddingAnimator(ANIMATOR_PADDING, new double[][] {previousPadding, targetPadding}, cancelableCallback);
}

private void updateTiltAnimator(float targetTilt, float previousTiltLevel,
@Nullable MapboxMap.CancelableCallback cancelableCallback) {
createNewCameraAdapterAnimator(ANIMATOR_TILT, new Float[] {previousTiltLevel, targetTilt}, cancelableCallback);
Expand Down Expand Up @@ -355,6 +367,16 @@ private void createNewCameraAdapterAnimator(@MapboxAnimator.Type int animatorTyp
}
}

private void createNewPaddingAnimator(@MapboxAnimator.Type int animatorType,
@NonNull @Size(min = 2) double[][] values,
@Nullable MapboxMap.CancelableCallback cancelableCallback) {
cancelAnimator(animatorType);
MapboxAnimator.AnimationsValueChangeListener listener = listeners.get(animatorType);
if (listener != null) {
animatorArray.put(animatorType, animatorProvider.paddingAnimator(values, listener, cancelableCallback));
}
}

private float checkGpsNorth(boolean isGpsNorth, float targetCameraBearing) {
if (isGpsNorth) {
targetCameraBearing = 0;
Expand Down Expand Up @@ -478,6 +500,10 @@ void cancelZoomAnimation() {
cancelAnimator(ANIMATOR_ZOOM);
}

void cancelPaddingAnimation() {
cancelAnimator(ANIMATOR_PADDING);
}

void cancelTiltAnimation() {
cancelAnimator(ANIMATOR_TILT);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ final class LocationCameraController {
private boolean isEnabled;

LocationCameraController(
Context context,
MapboxMap mapboxMap,
Transform transform,
OnCameraTrackingChangedListener internalCameraTrackingChangedListener,
@NonNull LocationComponentOptions options,
OnCameraMoveInvalidateListener onCameraMoveInvalidateListener) {
Context context,
MapboxMap mapboxMap,
Transform transform,
OnCameraTrackingChangedListener internalCameraTrackingChangedListener,
@NonNull LocationComponentOptions options,
OnCameraMoveInvalidateListener onCameraMoveInvalidateListener) {
this.mapboxMap = mapboxMap;
this.transform = transform;

Expand Down Expand Up @@ -123,7 +123,7 @@ void setCameraMode(@CameraMode.Mode final int cameraMode, @Nullable Location las
adjustGesturesThresholds();
notifyCameraTrackingChangeListener(wasTracking);
transitionToCurrentLocation(
wasTracking, lastLocation, transitionDuration, zoom, bearing, tilt, internalTransitionListener);
wasTracking, lastLocation, transitionDuration, zoom, bearing, tilt, internalTransitionListener);
}

/**
Expand Down Expand Up @@ -175,15 +175,15 @@ public void onFinish() {
CameraPosition currentPosition = mapboxMap.getCameraPosition();
if (Utils.immediateAnimation(mapboxMap.getProjection(), currentPosition.target, target)) {
transform.moveCamera(
mapboxMap,
update,
callback);
mapboxMap,
update,
callback);
} else {
transform.animateCamera(
mapboxMap,
update,
(int) transitionDuration,
callback);
mapboxMap,
update,
(int) transitionDuration,
callback);
}
} else {
if (internalTransitionListener != null) {
Expand Down Expand Up @@ -223,6 +223,15 @@ private void setZoom(float zoom) {
onCameraMoveInvalidateListener.onInvalidateCameraMove();
}

private void setPadding(double[] padding) {
if (isTransitioning) {
return;
}

transform.moveCamera(mapboxMap, CameraUpdateFactory.paddingTo(padding), null);
onCameraMoveInvalidateListener.onInvalidateCameraMove();
}

private void setTilt(float tilt) {
if (isTransitioning) {
return;
Expand All @@ -233,19 +242,14 @@ private void setTilt(float tilt) {
}

private final MapboxAnimator.AnimationsValueChangeListener<LatLng> latLngValueListener =
new MapboxAnimator.AnimationsValueChangeListener<LatLng>() {
@Override
public void onNewAnimationValue(LatLng value) {
setLatLng(value);
}
};
value -> setLatLng(value);

private final MapboxAnimator.AnimationsValueChangeListener<Float> gpsBearingValueListener =
new MapboxAnimator.AnimationsValueChangeListener<Float>() {
@Override
public void onNewAnimationValue(Float value) {
boolean trackingNorth = cameraMode == CameraMode.TRACKING_GPS_NORTH
&& mapboxMap.getCameraPosition().bearing == 0;
&& mapboxMap.getCameraPosition().bearing == 0;

if (!trackingNorth) {
setBearing(value);
Expand All @@ -258,27 +262,20 @@ public void onNewAnimationValue(Float value) {
@Override
public void onNewAnimationValue(Float value) {
if (cameraMode == CameraMode.TRACKING_COMPASS
|| cameraMode == CameraMode.NONE_COMPASS) {
|| cameraMode == CameraMode.NONE_COMPASS) {
setBearing(value);
}
}
};

private final MapboxAnimator.AnimationsValueChangeListener<Float> zoomValueListener =
new MapboxAnimator.AnimationsValueChangeListener<Float>() {
@Override
public void onNewAnimationValue(Float value) {
setZoom(value);
}
};
value -> setZoom(value);

private final MapboxAnimator.AnimationsValueChangeListener<double[]> paddingValueListener =
value -> setPadding(value);

private final MapboxAnimator.AnimationsValueChangeListener<Float> tiltValueListener =
new MapboxAnimator.AnimationsValueChangeListener<Float>() {
@Override
public void onNewAnimationValue(Float value) {
setTilt(value);
}
};
value -> setTilt(value);

Set<AnimatorListenerHolder> getAnimationListeners() {
Set<AnimatorListenerHolder> holders = new HashSet<>();
Expand All @@ -292,12 +289,13 @@ Set<AnimatorListenerHolder> getAnimationListeners() {

if (isConsumingCompass()) {
holders.add(new AnimatorListenerHolder(
MapboxAnimator.ANIMATOR_CAMERA_COMPASS_BEARING,
compassBearingValueListener));
MapboxAnimator.ANIMATOR_CAMERA_COMPASS_BEARING,
compassBearingValueListener));
}

holders.add(new AnimatorListenerHolder(MapboxAnimator.ANIMATOR_ZOOM, zoomValueListener));
holders.add(new AnimatorListenerHolder(MapboxAnimator.ANIMATOR_TILT, tiltValueListener));
holders.add(new AnimatorListenerHolder(MapboxAnimator.ANIMATOR_PADDING, paddingValueListener));
return holders;
}

Expand All @@ -318,7 +316,7 @@ private void adjustGesturesThresholds() {

boolean isConsumingCompass() {
return cameraMode == CameraMode.TRACKING_COMPASS
|| cameraMode == CameraMode.NONE_COMPASS;
|| cameraMode == CameraMode.NONE_COMPASS;
}

void setEnabled(boolean enabled) {
Expand All @@ -327,23 +325,23 @@ void setEnabled(boolean enabled) {

private boolean isLocationTracking() {
return cameraMode == CameraMode.TRACKING
|| cameraMode == CameraMode.TRACKING_COMPASS
|| cameraMode == CameraMode.TRACKING_GPS
|| cameraMode == CameraMode.TRACKING_GPS_NORTH;
|| cameraMode == CameraMode.TRACKING_COMPASS
|| cameraMode == CameraMode.TRACKING_GPS
|| cameraMode == CameraMode.TRACKING_GPS_NORTH;
}

private boolean isBearingTracking() {
return cameraMode == CameraMode.NONE_COMPASS
|| cameraMode == CameraMode.TRACKING_COMPASS
|| cameraMode == CameraMode.NONE_GPS
|| cameraMode == CameraMode.TRACKING_GPS
|| cameraMode == CameraMode.TRACKING_GPS_NORTH;
|| cameraMode == CameraMode.TRACKING_COMPASS
|| cameraMode == CameraMode.NONE_GPS
|| cameraMode == CameraMode.TRACKING_GPS
|| cameraMode == CameraMode.TRACKING_GPS_NORTH;
}

private boolean isLocationBearingTracking() {
return cameraMode == CameraMode.TRACKING_GPS
|| cameraMode == CameraMode.TRACKING_GPS_NORTH
|| cameraMode == CameraMode.NONE_GPS;
|| cameraMode == CameraMode.TRACKING_GPS_NORTH
|| cameraMode == CameraMode.NONE_GPS;
}

private void notifyCameraTrackingChangeListener(boolean wasTracking) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_FASTEST_INTERVAL_MILLIS;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_INTERVAL_MILLIS;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_TRACKING_PADDING_ANIM_DURATION;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_TRACKING_TILT_ANIM_DURATION;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.DEFAULT_TRACKING_ZOOM_ANIM_DURATION;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS;
Expand Down Expand Up @@ -598,6 +599,84 @@ public void cancelZoomWhileTrackingAnimation() {
locationAnimatorCoordinator.cancelZoomAnimation();
}

/**
* Sets the padding.
* This API can only be used in pair with camera modes other than {@link CameraMode#NONE}.
* If you are not using any of {@link CameraMode} modes,
* use one of {@link MapboxMap#moveCamera(CameraUpdate)},
* {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead.
* <p>
* If the camera is transitioning when the padding change is requested, the call is going to be ignored.
* Use {@link CameraTransitionListener} to chain the animations, or provide the padding as a camera change argument.
* </p>
*
* @param padding The desired padding.
*/
public void paddingWhileTracking(double[] padding) {
paddingWhileTracking(padding, DEFAULT_TRACKING_PADDING_ANIM_DURATION, null);
}

/**
* Sets the padding.
* This API can only be used in pair with camera modes other than {@link CameraMode#NONE}.
* If you are not using any of {@link CameraMode} modes,
* use one of {@link MapboxMap#moveCamera(CameraUpdate)},
* {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead.
* <p>
* If the camera is transitioning when the padding change is requested, the call is going to be ignored.
* Use {@link CameraTransitionListener} to chain the animations, or provide the padding as a camera change argument.
* </p>
*
* @param padding The desired padding.
* @param animationDuration The padding animation duration.
*/
public void paddingWhileTracking(double[] padding, long animationDuration) {
paddingWhileTracking(padding, animationDuration, null);
}

/**
* Sets the padding.
* This API can only be used in pair with camera modes other than {@link CameraMode#NONE}.
* If you are not using any of {@link CameraMode} modes,
* use one of {@link MapboxMap#moveCamera(CameraUpdate)},
* {@link MapboxMap#easeCamera(CameraUpdate)} or {@link MapboxMap#animateCamera(CameraUpdate)} instead.
* <p>
* If the camera is transitioning when the padding change is requested, the call is going to be ignored.
* Use {@link CameraTransitionListener} to chain the animations, or provide the padding as a camera change argument.
* </p>
*
* @param padding The desired padding.
* @param animationDuration The padding animation duration.
* @param callback The callback with finish/cancel information
*/
public void paddingWhileTracking(double[] padding, long animationDuration,
@Nullable MapboxMap.CancelableCallback callback) {
checkActivationState();
if (!isLayerReady) {
notifyUnsuccessfulCameraOperation(callback, null);
return;
} else if (getCameraMode() == CameraMode.NONE) {
notifyUnsuccessfulCameraOperation(callback, String.format("%s%s",
"LocationComponent#paddingWhileTracking method can only be used",
" when a camera mode other than CameraMode#NONE is engaged."));
return;
} else if (locationCameraController.isTransitioning()) {
notifyUnsuccessfulCameraOperation(callback,
"LocationComponent#paddingWhileTracking method call is ignored because the camera mode is transitioning");
return;
}

locationAnimatorCoordinator.feedNewPadding(padding, mapboxMap.getCameraPosition(), animationDuration, callback);
}

/**
* Cancels animation started by {@link #paddingWhileTracking(double[], long, MapboxMap.CancelableCallback)}.
*/
public void cancelPaddingWhileTrackingAnimation() {
checkActivationState();
locationAnimatorCoordinator.cancelPaddingAnimation();
}

/**
* Tilts the camera.
* This API can only be used in pair with camera modes other than {@link CameraMode#NONE}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public final class LocationComponentConstants {
// Default animation duration for zooming while tracking.
static final long DEFAULT_TRACKING_ZOOM_ANIM_DURATION = 750;

// Default animation duration for updating padding while tracking.
static final long DEFAULT_TRACKING_PADDING_ANIM_DURATION = 750;

// Default animation duration for tilting while tracking.
static final long DEFAULT_TRACKING_TILT_ANIM_DURATION = 1250;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ abstract class MapboxAnimator<K> extends ValueAnimator implements ValueAnimator.
ANIMATOR_LAYER_ACCURACY,
ANIMATOR_ZOOM,
ANIMATOR_TILT,
ANIMATOR_PULSING_CIRCLE
ANIMATOR_PULSING_CIRCLE,
ANIMATOR_PADDING
})
@interface Type {
}
Expand All @@ -44,6 +45,8 @@ abstract class MapboxAnimator<K> extends ValueAnimator implements ValueAnimator.
static final int ANIMATOR_ZOOM = 7;
static final int ANIMATOR_TILT = 8;
static final int ANIMATOR_PULSING_CIRCLE = 9;
static final int ANIMATOR_PADDING = 10;


private final AnimationsValueChangeListener<K> updateListener;
private final K target;
Expand Down
Loading

0 comments on commit acee2d4

Please sign in to comment.