Port: Allow setting padding when camera is tracking (#2165)
This commit is contained in:
@@ -31,6 +31,7 @@ import static org.maplibre.android.location.MapLibreAnimator.ANIMATOR_LAYER_ACCU
|
||||
import static org.maplibre.android.location.MapLibreAnimator.ANIMATOR_LAYER_COMPASS_BEARING;
|
||||
import static org.maplibre.android.location.MapLibreAnimator.ANIMATOR_LAYER_GPS_BEARING;
|
||||
import static org.maplibre.android.location.MapLibreAnimator.ANIMATOR_LAYER_LATLNG;
|
||||
import static org.maplibre.android.location.MapLibreAnimator.ANIMATOR_PADDING;
|
||||
import static org.maplibre.android.location.MapLibreAnimator.ANIMATOR_PULSING_CIRCLE;
|
||||
import static org.maplibre.android.location.MapLibreAnimator.ANIMATOR_TILT;
|
||||
import static org.maplibre.android.location.MapLibreAnimator.ANIMATOR_ZOOM;
|
||||
@@ -217,6 +218,12 @@ final class LocationAnimatorCoordinator {
|
||||
playAnimators(animationDuration, ANIMATOR_ZOOM);
|
||||
}
|
||||
|
||||
void feedNewPadding(double[] padding, @NonNull CameraPosition currentCameraPosition, long animationDuration,
|
||||
@Nullable MapLibreMap.CancelableCallback callback) {
|
||||
updatePaddingAnimator(padding, currentCameraPosition.padding, callback);
|
||||
playAnimators(animationDuration, ANIMATOR_PADDING);
|
||||
}
|
||||
|
||||
void feedNewTilt(double targetTilt, @NonNull CameraPosition currentCameraPosition, long animationDuration,
|
||||
@Nullable MapLibreMap.CancelableCallback callback) {
|
||||
updateTiltAnimator((float) targetTilt, (float) currentCameraPosition.tilt, callback);
|
||||
@@ -317,6 +324,11 @@ final class LocationAnimatorCoordinator {
|
||||
createNewCameraAdapterAnimator(ANIMATOR_ZOOM, new Float[] {previousZoomLevel, targetZoomLevel}, cancelableCallback);
|
||||
}
|
||||
|
||||
private void updatePaddingAnimator(double[] targetPadding, double[] previousPadding,
|
||||
@Nullable MapLibreMap.CancelableCallback cancelableCallback) {
|
||||
createNewPaddingAnimator(ANIMATOR_PADDING, new double[][] {previousPadding, targetPadding}, cancelableCallback);
|
||||
}
|
||||
|
||||
private void updateTiltAnimator(float targetTilt, float previousTiltLevel,
|
||||
@Nullable MapLibreMap.CancelableCallback cancelableCallback) {
|
||||
createNewCameraAdapterAnimator(ANIMATOR_TILT, new Float[] {previousTiltLevel, targetTilt}, cancelableCallback);
|
||||
@@ -356,6 +368,16 @@ final class LocationAnimatorCoordinator {
|
||||
}
|
||||
}
|
||||
|
||||
private void createNewPaddingAnimator(@MapLibreAnimator.Type int animatorType,
|
||||
@NonNull @Size(min = 2) double[][] values,
|
||||
@Nullable MapLibreMap.CancelableCallback cancelableCallback) {
|
||||
cancelAnimator(animatorType);
|
||||
MapLibreAnimator.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;
|
||||
@@ -479,6 +501,10 @@ final class LocationAnimatorCoordinator {
|
||||
cancelAnimator(ANIMATOR_ZOOM);
|
||||
}
|
||||
|
||||
void cancelPaddingAnimation() {
|
||||
cancelAnimator(ANIMATOR_PADDING);
|
||||
}
|
||||
|
||||
void cancelTiltAnimation() {
|
||||
cancelAnimator(ANIMATOR_TILT);
|
||||
}
|
||||
|
||||
@@ -224,6 +224,15 @@ final class LocationCameraController {
|
||||
onCameraMoveInvalidateListener.onInvalidateCameraMove();
|
||||
}
|
||||
|
||||
private void setPadding(double[] padding) {
|
||||
if (isTransitioning) {
|
||||
return;
|
||||
}
|
||||
|
||||
transform.moveCamera(maplibreMap, CameraUpdateFactory.paddingTo(padding), null);
|
||||
onCameraMoveInvalidateListener.onInvalidateCameraMove();
|
||||
}
|
||||
|
||||
private void setTilt(float tilt) {
|
||||
if (isTransitioning) {
|
||||
return;
|
||||
@@ -266,20 +275,13 @@ final class LocationCameraController {
|
||||
};
|
||||
|
||||
private final MapLibreAnimator.AnimationsValueChangeListener<Float> zoomValueListener =
|
||||
new MapLibreAnimator.AnimationsValueChangeListener<Float>() {
|
||||
@Override
|
||||
public void onNewAnimationValue(Float value) {
|
||||
setZoom(value);
|
||||
}
|
||||
};
|
||||
value -> setZoom(value);
|
||||
|
||||
private final MapLibreAnimator.AnimationsValueChangeListener<double[]> paddingValueListener =
|
||||
value -> setPadding(value);
|
||||
|
||||
private final MapLibreAnimator.AnimationsValueChangeListener<Float> tiltValueListener =
|
||||
new MapLibreAnimator.AnimationsValueChangeListener<Float>() {
|
||||
@Override
|
||||
public void onNewAnimationValue(Float value) {
|
||||
setTilt(value);
|
||||
}
|
||||
};
|
||||
value -> setTilt(value);
|
||||
|
||||
Set<AnimatorListenerHolder> getAnimationListeners() {
|
||||
Set<AnimatorListenerHolder> holders = new HashSet<>();
|
||||
@@ -299,6 +301,7 @@ final class LocationCameraController {
|
||||
|
||||
holders.add(new AnimatorListenerHolder(MapLibreAnimator.ANIMATOR_ZOOM, zoomValueListener));
|
||||
holders.add(new AnimatorListenerHolder(MapLibreAnimator.ANIMATOR_TILT, tiltValueListener));
|
||||
holders.add(new AnimatorListenerHolder(MapLibreAnimator.ANIMATOR_PADDING, paddingValueListener));
|
||||
return holders;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
|
||||
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
|
||||
import static org.maplibre.android.location.LocationComponentConstants.DEFAULT_FASTEST_INTERVAL_MILLIS;
|
||||
import static org.maplibre.android.location.LocationComponentConstants.DEFAULT_INTERVAL_MILLIS;
|
||||
import static org.maplibre.android.location.LocationComponentConstants.DEFAULT_TRACKING_PADDING_ANIM_DURATION;
|
||||
import static org.maplibre.android.location.LocationComponentConstants.DEFAULT_TRACKING_TILT_ANIM_DURATION;
|
||||
import static org.maplibre.android.location.LocationComponentConstants.DEFAULT_TRACKING_ZOOM_ANIM_DURATION;
|
||||
import static org.maplibre.android.location.LocationComponentConstants.TRANSITION_ANIMATION_DURATION_MS;
|
||||
@@ -603,6 +604,84 @@ public final class LocationComponent {
|
||||
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 MapLibreMap#moveCamera(CameraUpdate)},
|
||||
* {@link MapLibreMap#easeCamera(CameraUpdate)} or {@link MapLibreMap#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 MapLibreMap#moveCamera(CameraUpdate)},
|
||||
* {@link MapLibreMap#easeCamera(CameraUpdate)} or {@link MapLibreMap#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 MapLibreMap#moveCamera(CameraUpdate)},
|
||||
* {@link MapLibreMap#easeCamera(CameraUpdate)} or {@link MapLibreMap#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 MapLibreMap.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, maplibreMap.getCameraPosition(), animationDuration, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels animation started by {@link #paddingWhileTracking(double[], long, MapLibreMap.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}.
|
||||
@@ -732,10 +811,10 @@ public final class LocationComponent {
|
||||
* Example usage:
|
||||
* <pre>
|
||||
* {@code
|
||||
* mapboxMap.addOnCameraIdleListener(new MapboxMap.OnCameraIdleListener() {
|
||||
* MapLibreMap.addOnCameraIdleListener(new MapLibreMap.OnCameraIdleListener() {
|
||||
* {@literal @}Override
|
||||
* public void onCameraIdle() {
|
||||
* double zoom = mapboxMap.getCameraPosition().zoom;
|
||||
* double zoom = MapLibreMap.getCameraPosition().zoom;
|
||||
* int maxAnimationFps;
|
||||
* if (zoom < 5) {
|
||||
* maxAnimationFps = 3;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
*
|
||||
* @param <K> Data type that will be animated.
|
||||
*/
|
||||
abstract class MapLibreAnimator<K> extends ValueAnimator implements ValueAnimator.AnimatorUpdateListener {
|
||||
public abstract class MapLibreAnimator<K> extends ValueAnimator implements ValueAnimator.AnimatorUpdateListener {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef( {
|
||||
ANIMATOR_LAYER_LATLNG,
|
||||
@@ -29,7 +29,8 @@ abstract class MapLibreAnimator<K> extends ValueAnimator implements ValueAnimato
|
||||
ANIMATOR_LAYER_ACCURACY,
|
||||
ANIMATOR_ZOOM,
|
||||
ANIMATOR_TILT,
|
||||
ANIMATOR_PULSING_CIRCLE
|
||||
ANIMATOR_PULSING_CIRCLE,
|
||||
ANIMATOR_PADDING
|
||||
})
|
||||
@interface Type {
|
||||
}
|
||||
@@ -44,6 +45,7 @@ abstract class MapLibreAnimator<K> extends ValueAnimator implements ValueAnimato
|
||||
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;
|
||||
@@ -59,7 +61,7 @@ abstract class MapLibreAnimator<K> extends ValueAnimator implements ValueAnimato
|
||||
*/
|
||||
private boolean invalid;
|
||||
|
||||
MapLibreAnimator(@NonNull @Size(min = 2) K[] values, @NonNull AnimationsValueChangeListener<K> updateListener,
|
||||
public MapLibreAnimator(@NonNull @Size(min = 2) K[] values, @NonNull AnimationsValueChangeListener<K> updateListener,
|
||||
int maxAnimationFps) {
|
||||
minUpdateInterval = 1E9 / maxAnimationFps;
|
||||
setObjectValues((Object[]) values);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.maplibre.android.location
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import org.maplibre.android.maps.MapLibreMap
|
||||
|
||||
internal class MapLibreAnimatorListener(cancelableCallback: MapLibreMap.CancelableCallback?) :
|
||||
AnimatorListenerAdapter() {
|
||||
private val cancelableCallback: MapLibreMap.CancelableCallback?
|
||||
|
||||
init {
|
||||
this.cancelableCallback = cancelableCallback
|
||||
}
|
||||
|
||||
override fun onAnimationCancel(animation: Animator) {
|
||||
cancelableCallback?.onCancel()
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
cancelableCallback?.onFinish()
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,12 @@ final class MapLibreAnimatorProvider {
|
||||
return new MapLibreCameraAnimatorAdapter(values, updateListener, cancelableCallback);
|
||||
}
|
||||
|
||||
MapLibrePaddingAnimator paddingAnimator(double[][] values,
|
||||
MapLibreAnimator.AnimationsValueChangeListener<double[]> updateListener,
|
||||
@Nullable MapLibreMap.CancelableCallback cancelableCallback) {
|
||||
return new MapLibrePaddingAnimator(values, updateListener, cancelableCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* This animator is for the LocationComponent pulsing circle.
|
||||
*
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package org.maplibre.android.location;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Size;
|
||||
@@ -10,30 +7,11 @@ import androidx.annotation.Size;
|
||||
import org.maplibre.android.maps.MapLibreMap;
|
||||
|
||||
class MapLibreCameraAnimatorAdapter extends MapLibreFloatAnimator {
|
||||
@Nullable
|
||||
private final MapLibreMap.CancelableCallback cancelableCallback;
|
||||
|
||||
MapLibreCameraAnimatorAdapter(@NonNull @Size(min = 2) Float[] values,
|
||||
AnimationsValueChangeListener updateListener,
|
||||
@Nullable MapLibreMap.CancelableCallback cancelableCallback) {
|
||||
super(values, updateListener, Integer.MAX_VALUE);
|
||||
this.cancelableCallback = cancelableCallback;
|
||||
addListener(new MapLibreAnimatorListener());
|
||||
}
|
||||
|
||||
private final class MapLibreAnimatorListener extends AnimatorListenerAdapter {
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
if (cancelableCallback != null) {
|
||||
cancelableCallback.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (cancelableCallback != null) {
|
||||
cancelableCallback.onFinish();
|
||||
}
|
||||
}
|
||||
addListener(new MapLibreAnimatorListener(cancelableCallback));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.maplibre.android.location
|
||||
|
||||
import android.animation.TypeEvaluator
|
||||
import androidx.annotation.Size
|
||||
import org.maplibre.android.maps.MapLibreMap.CancelableCallback
|
||||
|
||||
class MapLibrePaddingAnimator internal constructor(
|
||||
@Size(min = 2) values: Array<DoubleArray>,
|
||||
updateListener: AnimationsValueChangeListener<DoubleArray>,
|
||||
cancelableCallback: CancelableCallback?
|
||||
) :
|
||||
MapLibreAnimator<DoubleArray>(values, updateListener, Int.MAX_VALUE) {
|
||||
init {
|
||||
addListener(MapLibreAnimatorListener(cancelableCallback))
|
||||
}
|
||||
|
||||
public override fun provideEvaluator(): TypeEvaluator<DoubleArray> {
|
||||
return PaddingEvaluator()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.maplibre.android.location
|
||||
|
||||
import android.animation.TypeEvaluator
|
||||
import androidx.annotation.Size
|
||||
|
||||
internal class PaddingEvaluator : TypeEvaluator<DoubleArray> {
|
||||
private val padding = DoubleArray(4)
|
||||
override fun evaluate(
|
||||
fraction: Float, @Size(min = 4) startValue: DoubleArray,
|
||||
@Size(min = 4) endValue: DoubleArray
|
||||
): DoubleArray {
|
||||
padding[0] = startValue[0] + (endValue[0] - startValue[0]) * fraction
|
||||
padding[1] = startValue[1] + (endValue[1] - startValue[1]) * fraction
|
||||
padding[2] = startValue[2] + (endValue[2] - startValue[2]) * fraction
|
||||
padding[3] = startValue[3] + (endValue[3] - startValue[3]) * fraction
|
||||
return padding
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import org.junit.Assert.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.maplibre.android.location.LocationComponentConstants.DEFAULT_TRACKING_PADDING_ANIM_DURATION
|
||||
import org.mockito.Mockito
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.maplibre.testUtils.Assert as MapLibreAssert
|
||||
@@ -58,7 +59,8 @@ class LocationAnimatorCoordinatorTest {
|
||||
ANIMATOR_CAMERA_COMPASS_BEARING,
|
||||
ANIMATOR_LAYER_ACCURACY,
|
||||
ANIMATOR_ZOOM,
|
||||
ANIMATOR_TILT
|
||||
ANIMATOR_TILT,
|
||||
ANIMATOR_PADDING
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -110,6 +112,19 @@ class LocationAnimatorCoordinatorTest {
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
val doubleArraySlot = slot<Array<DoubleArray>>()
|
||||
val doubleArrayListenerSlot = slot<AnimationsValueChangeListener<DoubleArray>>()
|
||||
every {
|
||||
animatorProvider.paddingAnimator(capture(doubleArraySlot), capture(doubleArrayListenerSlot), capture(callback))
|
||||
} answers {
|
||||
MapLibrePaddingAnimator(doubleArraySlot.captured, doubleArrayListenerSlot.captured, callback.captured)
|
||||
}
|
||||
every {
|
||||
animatorProvider.paddingAnimator(capture(doubleArraySlot), capture(doubleArrayListenerSlot), null)
|
||||
} answers {
|
||||
MapLibrePaddingAnimator(doubleArraySlot.captured, doubleArrayListenerSlot.captured, null)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -504,6 +519,33 @@ class LocationAnimatorCoordinatorTest {
|
||||
verify { animatorSetProvider.startAnimation(eq(listOf(animator)), any<LinearInterpolator>(), DEFAULT_TRACKING_ZOOM_ANIM_DURATION) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun feedNewPadding_animatorsCreated() {
|
||||
locationAnimatorCoordinator.feedNewPadding(
|
||||
doubleArrayOf(100.0, 200.0, 300.0, 400.0),
|
||||
cameraPosition,
|
||||
DEFAULT_TRACKING_PADDING_ANIM_DURATION,
|
||||
null
|
||||
)
|
||||
|
||||
assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_PADDING] != null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun feedNewPadding_animatorValue() {
|
||||
val padding = doubleArrayOf(100.0, 200.0, 300.0, 400.0)
|
||||
locationAnimatorCoordinator.feedNewPadding(
|
||||
padding,
|
||||
cameraPosition,
|
||||
DEFAULT_TRACKING_PADDING_ANIM_DURATION,
|
||||
null
|
||||
)
|
||||
|
||||
val animator = locationAnimatorCoordinator.animatorArray[ANIMATOR_PADDING]
|
||||
assertTrue(padding.contentEquals(animator.target as DoubleArray))
|
||||
verify { animatorSetProvider.startAnimation(eq(listOf(animator)), any<LinearInterpolator>(), DEFAULT_TRACKING_PADDING_ANIM_DURATION) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun feedNewTiltLevel_animatorsCreated() {
|
||||
locationAnimatorCoordinator.feedNewTilt(
|
||||
@@ -556,6 +598,21 @@ class LocationAnimatorCoordinatorTest {
|
||||
assertFalse(locationAnimatorCoordinator.animatorArray[ANIMATOR_ZOOM].isStarted)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cancelPaddingAnimators() {
|
||||
locationAnimatorCoordinator.feedNewPadding(
|
||||
doubleArrayOf(100.0, 200.0, 300.0, 400.0),
|
||||
cameraPosition,
|
||||
DEFAULT_TRACKING_PADDING_ANIM_DURATION,
|
||||
null
|
||||
)
|
||||
assertTrue(locationAnimatorCoordinator.animatorArray[ANIMATOR_PADDING].isStarted)
|
||||
|
||||
locationAnimatorCoordinator.cancelPaddingAnimation()
|
||||
|
||||
assertFalse(locationAnimatorCoordinator.animatorArray[ANIMATOR_PADDING].isStarted)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cancelTiltAnimation() {
|
||||
locationAnimatorCoordinator.feedNewTilt(
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.maplibre.android.utils.BitmapUtils
|
||||
import org.maplibre.android.utils.ColorUtils
|
||||
import org.hamcrest.CoreMatchers.*
|
||||
import org.junit.*
|
||||
import org.junit.Assert.assertArrayEquals
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.runner.RunWith
|
||||
@@ -1608,6 +1609,122 @@ class LocationComponentTest : EspressoTest() {
|
||||
executeComponentTest(componentAction)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun animators_dontPaddingWhileNotTracking() {
|
||||
val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction {
|
||||
override fun onLocationComponentAction(
|
||||
component: LocationComponent,
|
||||
maplibreMap: MapLibreMap,
|
||||
style: Style,
|
||||
uiController: UiController,
|
||||
context: Context
|
||||
) {
|
||||
component.activateLocationComponent(LocationComponentActivationOptions
|
||||
.builder(context, style)
|
||||
.useDefaultLocationEngine(false)
|
||||
.build())
|
||||
component.isLocationComponentEnabled = true
|
||||
component.cameraMode = CameraMode.NONE
|
||||
val padding = maplibreMap.cameraPosition.padding
|
||||
component.paddingWhileTracking(doubleArrayOf(100.0, 200.0, 300.0, 400.0))
|
||||
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_PADDING_ANIM_DURATION)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
|
||||
assertArrayEquals(padding, maplibreMap.cameraPosition.padding, 0.1)
|
||||
}
|
||||
}
|
||||
|
||||
executeComponentTest(componentAction)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun animators_dontPaddingWhileStopped() {
|
||||
val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction {
|
||||
override fun onLocationComponentAction(
|
||||
component: LocationComponent,
|
||||
maplibreMap: MapLibreMap,
|
||||
style: Style,
|
||||
uiController: UiController,
|
||||
context: Context
|
||||
) {
|
||||
component.activateLocationComponent(LocationComponentActivationOptions
|
||||
.builder(context, style)
|
||||
.useDefaultLocationEngine(false)
|
||||
.build())
|
||||
component.isLocationComponentEnabled = true
|
||||
component.cameraMode = CameraMode.TRACKING
|
||||
val padding = maplibreMap.cameraPosition.padding
|
||||
|
||||
component.onStop()
|
||||
component.paddingWhileTracking(doubleArrayOf(100.0, 200.0, 300.0, 400.0))
|
||||
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_PADDING_ANIM_DURATION)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
|
||||
assertArrayEquals(padding, maplibreMap.cameraPosition.padding, 0.1)
|
||||
}
|
||||
}
|
||||
|
||||
executeComponentTest(componentAction)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun animators_dontPaddingWhileTransitioning() {
|
||||
val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction {
|
||||
override fun onLocationComponentAction(
|
||||
component: LocationComponent,
|
||||
maplibreMap: MapLibreMap,
|
||||
style: Style,
|
||||
uiController: UiController,
|
||||
context: Context
|
||||
) {
|
||||
component.activateLocationComponent(LocationComponentActivationOptions
|
||||
.builder(context, style)
|
||||
.useDefaultLocationEngine(false)
|
||||
.build())
|
||||
component.isLocationComponentEnabled = true
|
||||
component.forceLocationUpdate(location)
|
||||
|
||||
val padding = maplibreMap.cameraPosition.padding
|
||||
component.setCameraMode(CameraMode.TRACKING_GPS, 500L, null, null, null, null)
|
||||
component.paddingWhileTracking(doubleArrayOf(100.0, 200.0, 300.0, 400.0), 1000L)
|
||||
uiController.loopMainThreadForAtLeast(1000L)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
|
||||
assertArrayEquals(padding, maplibreMap.cameraPosition.padding, 0.1)
|
||||
}
|
||||
}
|
||||
|
||||
executeComponentTest(componentAction)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun animators_paddingWhileTracking() {
|
||||
val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction {
|
||||
override fun onLocationComponentAction(
|
||||
component: LocationComponent,
|
||||
maplibreMap: MapLibreMap,
|
||||
style: Style,
|
||||
uiController: UiController,
|
||||
context: Context
|
||||
) {
|
||||
component.activateLocationComponent(LocationComponentActivationOptions
|
||||
.builder(context, style)
|
||||
.useDefaultLocationEngine(false)
|
||||
.build())
|
||||
component.isLocationComponentEnabled = true
|
||||
component.cameraMode = CameraMode.TRACKING
|
||||
val padding = doubleArrayOf(100.0, 200.0, 300.0, 400.0)
|
||||
component.paddingWhileTracking(padding)
|
||||
uiController.loopMainThreadForAtLeast(DEFAULT_TRACKING_PADDING_ANIM_DURATION)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
|
||||
assertArrayEquals(padding, maplibreMap.cameraPosition.padding, 0.01)
|
||||
}
|
||||
}
|
||||
|
||||
executeComponentTest(componentAction)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cameraPositionAdjustedToTrackingModeWhenComponentEnabled() {
|
||||
val componentAction = object : LocationComponentAction.OnPerformLocationComponentAction {
|
||||
|
||||
@@ -25,12 +25,13 @@ import org.maplibre.android.location.modes.CameraMode
|
||||
import org.maplibre.android.location.modes.RenderMode
|
||||
import org.maplibre.android.location.permissions.PermissionsListener
|
||||
import org.maplibre.android.location.permissions.PermissionsManager
|
||||
import org.maplibre.android.maps.MapView
|
||||
import org.maplibre.android.maps.MapLibreMap
|
||||
import org.maplibre.android.maps.MapLibreMap.CancelableCallback
|
||||
import org.maplibre.android.maps.MapView
|
||||
import org.maplibre.android.maps.OnMapReadyCallback
|
||||
import org.maplibre.android.maps.Style
|
||||
import org.maplibre.android.testapp.R
|
||||
import java.util.Random
|
||||
|
||||
class LocationModesActivity :
|
||||
AppCompatActivity(),
|
||||
@@ -193,6 +194,27 @@ class LocationModesActivity :
|
||||
Toast.makeText(this, "Not possible to animate - not tracking", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
} else if (id == R.id.action_component_padding_animation_while_tracking) {
|
||||
val paddingRandom = Random()
|
||||
locationComponent!!.paddingWhileTracking(
|
||||
doubleArrayOf(
|
||||
paddingRandom.nextDouble() * 500,
|
||||
paddingRandom.nextDouble() * 500,
|
||||
paddingRandom.nextDouble() * 500,
|
||||
paddingRandom.nextDouble() * 500
|
||||
), 1000L, object : CancelableCallback {
|
||||
override fun onCancel() {
|
||||
// No impl
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
locationComponent!!.zoomWhileTracking(16.0)
|
||||
}
|
||||
})
|
||||
if (locationComponent!!.getCameraMode() == CameraMode.NONE) {
|
||||
Toast.makeText(this, "Not possible to animate - not tracking", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
@@ -36,4 +36,8 @@
|
||||
<item android:id="@+id/action_component_animate_while_tracking"
|
||||
android:title="Animate while tracking"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item android:id="@+id/action_component_padding_animation_while_tracking"
|
||||
android:title="PaddingAnimation while tracking"
|
||||
app:showAsAction="never"/>
|
||||
</menu>
|
||||
Reference in New Issue
Block a user