[android] immediate location animation based on map's projection

This commit is contained in:
Łukasz Paczos
2018-12-11 19:00:15 +01:00
committed by Łukasz Paczos
parent bbeec8dacb
commit e86d1b2ac9
8 changed files with 89 additions and 15 deletions

View File

@@ -13,6 +13,7 @@ import android.view.animation.LinearInterpolator;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Projection;
import java.util.ArrayList;
import java.util.List;
@@ -39,12 +40,17 @@ final class LocationAnimatorCoordinator {
final List<MapboxAnimator.OnLayerAnimationsValuesChangeListener> layerListeners = new ArrayList<>();
final List<MapboxAnimator.OnCameraAnimationsValuesChangeListener> cameraListeners = new ArrayList<>();
private final Projection projection;
private Location previousLocation;
private float previousAccuracyRadius = -1;
private float previousCompassBearing = -1;
private long locationUpdateTimestamp = -1;
private float durationMultiplier;
LocationAnimatorCoordinator(Projection projection) {
this.projection = projection;
}
void addLayerListener(MapboxAnimator.OnLayerAnimationsValuesChangeListener listener) {
layerListeners.add(listener);
}
@@ -81,8 +87,8 @@ final class LocationAnimatorCoordinator {
updateLayerAnimators(previousLayerLatLng, targetLatLng, previousLayerBearing, targetLayerBearing);
updateCameraAnimators(previousCameraLatLng, previousCameraBearing, targetLatLng, targetCameraBearing);
boolean snap = immediateAnimation(previousCameraLatLng, targetLatLng, currentCameraPosition.zoom)
|| immediateAnimation(previousLayerLatLng, targetLatLng, currentCameraPosition.zoom);
boolean snap = immediateAnimation(projection, previousCameraLatLng, targetLatLng)
|| immediateAnimation(projection, previousLayerLatLng, targetLatLng);
playLocationAnimators(snap ? 0 : getAnimationDuration());
previousLocation = newLocation;
@@ -317,7 +323,7 @@ final class LocationAnimatorCoordinator {
createNewAnimator(ANIMATOR_CAMERA_LATLNG,
new CameraLatLngAnimator(previousCameraTarget, currentTarget, cameraListeners));
return immediateAnimation(previousCameraTarget, currentTarget, currentCameraPosition.zoom);
return immediateAnimation(projection, previousCameraTarget, currentTarget);
}
private void resetCameraGpsBearingAnimation(@NonNull CameraPosition currentCameraPosition, boolean isGpsNorth) {

View File

@@ -129,7 +129,7 @@ final class LocationCameraController implements MapboxAnimator.OnCameraAnimation
};
CameraPosition currentPosition = mapboxMap.getCameraPosition();
if (Utils.immediateAnimation(currentPosition.target, target, currentPosition.zoom)) {
if (Utils.immediateAnimation(mapboxMap.getProjection(), currentPosition.target, target)) {
mapboxMap.moveCamera(
update,
callback);

View File

@@ -1015,7 +1015,7 @@ public final class LocationComponent {
locationCameraController = new LocationCameraController(
context, mapboxMap, cameraTrackingChangedListener, options, onCameraMoveInvalidateListener);
locationAnimatorCoordinator = new LocationAnimatorCoordinator();
locationAnimatorCoordinator = new LocationAnimatorCoordinator(mapboxMap.getProjection());
locationAnimatorCoordinator.addLayerListener(locationLayerController);
locationAnimatorCoordinator.addCameraListener(locationCameraController);
locationAnimatorCoordinator.setTrackingAnimationDurationMultiplier(options

View File

@@ -24,7 +24,7 @@ final class LocationComponentConstants {
static final long DEFAULT_TRACKING_TILT_ANIM_DURATION = 1250;
// Threshold value to perform immediate camera/layer position update.
static final double INSTANT_LOCATION_TRANSITION_THRESHOLD = 500_000;
static final double INSTANT_LOCATION_TRANSITION_THRESHOLD = 50_000;
// Default interval between location updates
static final long DEFAULT_INTERVAL_MILLIS = 1000;

View File

@@ -16,6 +16,7 @@ import android.support.v4.content.ContextCompat;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Projection;
import static com.mapbox.mapboxsdk.location.LocationComponentConstants.INSTANT_LOCATION_TRANSITION_THRESHOLD;
@@ -92,13 +93,10 @@ public final class Utils {
return (float) (location.getAccuracy() * (1 / metersPerPixel));
}
static boolean immediateAnimation(LatLng current, @NonNull LatLng target, double zoom) {
// TODO: calculate the value based on the projection
static boolean immediateAnimation(@NonNull Projection projection, @NonNull LatLng current, @NonNull LatLng target) {
double metersPerPixel = projection.getMetersPerPixelAtLatitude((current.getLatitude() + target.getLatitude()) / 2);
double distance = current.distanceTo(target);
if (zoom > 10) {
distance *= zoom;
}
return distance > INSTANT_LOCATION_TRANSITION_THRESHOLD;
return distance / metersPerPixel > INSTANT_LOCATION_TRANSITION_THRESHOLD;
}
/**