[android] reworked zoomIn and zoomOut to use ValueAnimators (#11382)

This commit is contained in:
Łukasz Paczos
2018-03-05 14:23:28 +01:00
committed by GitHub
parent 8ed540ea7b
commit c0bb9aaa81
4 changed files with 111 additions and 79 deletions

View File

@@ -218,15 +218,17 @@ final class MapGestureDetector {
}
void cancelAnimators() {
if (scaleAnimator != null) {
scaleAnimator.cancel();
}
if (rotateAnimator != null) {
rotateAnimator.cancel();
}
animationsTimeoutHandler.removeCallbacksAndMessages(null);
scheduledAnimators.clear();
cancelAnimator(scaleAnimator);
cancelAnimator(rotateAnimator);
}
private void cancelAnimator(Animator animator) {
if (animator != null && animator.isStarted()) {
animator.cancel();
}
}
/**
@@ -338,15 +340,18 @@ final class MapGestureDetector {
transform.cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
PointF zoomFocalPoint;
// Single finger double tap
if (focalPoint != null) {
// User provided focal point
transform.zoomIn(focalPoint);
zoomFocalPoint = focalPoint;
} else {
// Zoom in on gesture
transform.zoomIn(new PointF(motionEvent.getX(), motionEvent.getY()));
zoomFocalPoint = new PointF(motionEvent.getX(), motionEvent.getY());
}
zoomInAnimated(zoomFocalPoint, false);
sendTelemetryEvent(Events.DOUBLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY()));
return true;
@@ -512,7 +517,7 @@ final class MapGestureDetector {
double zoomAddition = calculateScale(velocityXY, detector.isScalingOut());
double currentZoom = transform.getRawZoom();
long animationTime = (long) (Math.abs(zoomAddition) * 1000 / 4);
scaleAnimator = createScaleAnimator(currentZoom, zoomAddition, animationTime);
scaleAnimator = createScaleAnimator(currentZoom, zoomAddition, scaleFocalPoint, animationTime);
scheduleAnimator(scaleAnimator);
}
@@ -540,39 +545,6 @@ final class MapGestureDetector {
return zoomAddition;
}
private Animator createScaleAnimator(double currentZoom, double zoomAddition, long animationTime) {
ValueAnimator animator = ValueAnimator.ofFloat((float) currentZoom, (float) (currentZoom + zoomAddition));
animator.setDuration(animationTime);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
transform.setZoom((Float) animation.getAnimatedValue(), scaleFocalPoint, 0);
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
transform.cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_ANIMATION);
}
@Override
public void onAnimationCancel(Animator animation) {
transform.cancelTransitions();
}
@Override
public void onAnimationEnd(Animator animation) {
cameraChangeDispatcher.onCameraIdle();
}
});
return animator;
}
private double getNewZoom(float scaleFactor, boolean quickZoom) {
double zoomBy = Math.log(scaleFactor) / Math.log(Math.PI / 2);
if (quickZoom) {
@@ -776,16 +748,95 @@ final class MapGestureDetector {
transform.cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
PointF zoomFocalPoint;
// Single finger double tap
if (focalPoint != null) {
transform.zoomOut(focalPoint);
// User provided focal point
zoomFocalPoint = focalPoint;
} else {
transform.zoomOut(detector.getFocalPoint());
// Zoom in on gesture
zoomFocalPoint = detector.getFocalPoint();
}
zoomOutAnimated(zoomFocalPoint, false);
return true;
}
}
private Animator createScaleAnimator(double currentZoom, double zoomAddition, PointF animationFocalPoint,
long animationTime) {
ValueAnimator animator = ValueAnimator.ofFloat((float) currentZoom, (float) (currentZoom + zoomAddition));
animator.setDuration(animationTime);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
transform.setZoom((Float) animation.getAnimatedValue(), animationFocalPoint);
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
transform.cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_ANIMATION);
}
@Override
public void onAnimationCancel(Animator animation) {
transform.cancelTransitions();
}
@Override
public void onAnimationEnd(Animator animation) {
cameraChangeDispatcher.onCameraIdle();
}
});
return animator;
}
/**
* Zoom in by 1.
*
* @param zoomFocalPoint focal point of zoom animation
* @param runImmediately if true, animation will be started right away, otherwise it will wait until
* {@link MotionEvent#ACTION_UP} is registered.
*/
void zoomInAnimated(PointF zoomFocalPoint, boolean runImmediately) {
zoomAnimated(true, zoomFocalPoint, runImmediately);
}
/**
* Zoom out by 1.
*
* @param zoomFocalPoint focal point of zoom animation
* @param runImmediately if true, animation will be started right away, otherwise it will wait until
* {@link MotionEvent#ACTION_UP} is registered.
*/
void zoomOutAnimated(PointF zoomFocalPoint, boolean runImmediately) {
zoomAnimated(false, zoomFocalPoint, runImmediately);
}
private void zoomAnimated(boolean zoomIn, PointF zoomFocalPoint, boolean runImmediately) {
//canceling here as well, because when using a button it will not be canceled automatically by onDown()
cancelAnimator(scaleAnimator);
double currentZoom = transform.getRawZoom();
scaleAnimator = createScaleAnimator(
currentZoom,
zoomIn ? 1 : -1,
zoomFocalPoint,
MapboxConstants.ANIMATION_DURATION);
if (runImmediately) {
scaleAnimator.start();
} else {
scheduleAnimator(scaleAnimator);
}
}
private void sendTelemetryEvent(String eventType, PointF focalPoint) {
if (isZoomValid(transform)) {
MapEventFactory mapEventFactory = new MapEventFactory();

View File

@@ -21,12 +21,14 @@ final class MapKeyListener {
private final Transform transform;
private final UiSettings uiSettings;
private final MapGestureDetector mapGestureDetector;
private TrackballLongPressTimeOut currentTrackballLongPressTimeOut;
MapKeyListener(@NonNull Transform transform, @NonNull UiSettings uiSettings) {
MapKeyListener(Transform transform, UiSettings uiSettings, MapGestureDetector mapGestureDetector) {
this.transform = transform;
this.uiSettings = uiSettings;
this.mapGestureDetector = mapGestureDetector;
}
/**
@@ -124,7 +126,7 @@ final class MapKeyListener {
// Zoom out
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
transform.zoomOut(focalPoint);
mapGestureDetector.zoomOutAnimated(focalPoint, true);
return true;
default:
@@ -160,7 +162,7 @@ final class MapKeyListener {
// Zoom in
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
transform.zoomIn(focalPoint);
mapGestureDetector.zoomInAnimated(focalPoint, true);
return true;
}
@@ -215,7 +217,7 @@ final class MapKeyListener {
if (currentTrackballLongPressTimeOut != null) {
// Zoom in
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
transform.zoomIn(focalPoint);
mapGestureDetector.zoomInAnimated(focalPoint, true);
}
return true;
@@ -257,7 +259,7 @@ final class MapKeyListener {
if (!cancelled) {
// Zoom out
PointF pointF = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
transform.zoomOut(pointF);
mapGestureDetector.zoomOutAnimated(pointF, true);
// Ensure the up action is not run
currentTrackballLongPressTimeOut = null;

View File

@@ -29,7 +29,6 @@ import com.mapbox.android.telemetry.Event;
import com.mapbox.android.telemetry.MapEventFactory;
import com.mapbox.android.telemetry.MapboxTelemetry;
import com.mapbox.mapboxsdk.BuildConfig;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
@@ -177,12 +176,12 @@ public class MapView extends FrameLayout {
// user input
mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings,
annotationManager, cameraChangeDispatcher);
mapKeyListener = new MapKeyListener(transform, uiSettings);
mapKeyListener = new MapKeyListener(transform, uiSettings, mapGestureDetector);
// overlain zoom buttons
mapZoomButtonController = new MapZoomButtonController(new ZoomButtonsController(this));
MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform,
cameraChangeDispatcher, getWidth(), getHeight());
MapZoomControllerListener zoomListener = new MapZoomControllerListener(
mapGestureDetector, cameraChangeDispatcher, getWidth(), getHeight());
mapZoomButtonController.bind(uiSettings, zoomListener);
compassView.injectCompassAnimationListener(createCompassAnimationListener(cameraChangeDispatcher));
@@ -1030,17 +1029,13 @@ public class MapView extends FrameLayout {
private static class MapZoomControllerListener implements ZoomButtonsController.OnZoomListener {
private final MapGestureDetector mapGestureDetector;
private final UiSettings uiSettings;
private final Transform transform;
private final CameraChangeDispatcher cameraChangeDispatcher;
private final float mapWidth;
private final float mapHeight;
MapZoomControllerListener(MapGestureDetector detector, UiSettings uiSettings, Transform transform,
CameraChangeDispatcher dispatcher, float mapWidth, float mapHeight) {
MapZoomControllerListener(MapGestureDetector detector, CameraChangeDispatcher dispatcher,
float mapWidth, float mapHeight) {
this.mapGestureDetector = detector;
this.uiSettings = uiSettings;
this.transform = transform;
this.cameraChangeDispatcher = dispatcher;
this.mapWidth = mapWidth;
this.mapHeight = mapHeight;
@@ -1064,9 +1059,9 @@ public class MapView extends FrameLayout {
focalPoint = new PointF(mapWidth / 2, mapHeight / 2);
}
if (zoomIn) {
transform.zoomIn(focalPoint);
mapGestureDetector.zoomInAnimated(focalPoint, true);
} else {
transform.zoomOut(focalPoint);
mapGestureDetector.zoomOutAnimated(focalPoint, true);
}
}
}

View File

@@ -226,24 +226,8 @@ final class Transform implements MapView.OnMapChangedListener {
return mapView.getZoom();
}
void zoomIn(@NonNull PointF focalPoint) {
CameraPosition cameraPosition = invalidateCameraPosition();
if (cameraPosition != null) {
int newZoom = (int) Math.round(cameraPosition.zoom + 1);
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION);
}
}
void zoomOut(@NonNull PointF focalPoint) {
CameraPosition cameraPosition = invalidateCameraPosition();
if (cameraPosition != null) {
int newZoom = (int) Math.round(cameraPosition.zoom - 1);
setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION);
}
}
void zoomBy(double zoomAddition, @NonNull PointF focalPoint) {
setZoom(mapView.getZoom() + zoomAddition, focalPoint, 0);
setZoom(mapView.getZoom() + zoomAddition, focalPoint);
}
void setZoom(double zoom, @NonNull PointF focalPoint) {