Port: Allow setting padding when camera is tracking (#2165)

This commit is contained in:
Bart Louwers
2024-03-04 20:27:09 +01:00
committed by GitHub
parent d261bf54df
commit 69f983b83d
14 changed files with 399 additions and 42 deletions

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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()
}
}

View File

@@ -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.
*

View File

@@ -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));
}
}

View File

@@ -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()
}
}

View File

@@ -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
}
}

View File

@@ -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(

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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>