Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[android] reworked zoomIn and zoomOut to use ValueAnimators (#11382)
Browse files Browse the repository at this point in the history
  • Loading branch information
LukasPaczos committed Mar 5, 2018
1 parent 8ed540e commit c0bb9aa
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,17 @@ boolean onTouchEvent(MotionEvent motionEvent) {
}

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

/**
Expand Down Expand Up @@ -338,15 +340,18 @@ public boolean onDoubleTapEvent(MotionEvent motionEvent) {
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;
Expand Down Expand Up @@ -512,7 +517,7 @@ public void onScaleEnd(StandardScaleGestureDetector detector, float velocityX, f
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);
}

Expand Down Expand Up @@ -540,39 +545,6 @@ private double calculateScale(double velocityXY, boolean isScalingOut) {
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) {
Expand Down Expand Up @@ -776,16 +748,95 @@ public boolean onMultiFingerTap(MultiFingerTapGestureDetector detector, int poin
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -124,7 +126,7 @@ boolean onKeyLongPress(int keyCode, KeyEvent event) {

// Zoom out
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
transform.zoomOut(focalPoint);
mapGestureDetector.zoomOutAnimated(focalPoint, true);
return true;

default:
Expand Down Expand Up @@ -160,7 +162,7 @@ boolean onKeyUp(int keyCode, KeyEvent event) {

// Zoom in
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
transform.zoomIn(focalPoint);
mapGestureDetector.zoomInAnimated(focalPoint, true);
return true;
}

Expand Down Expand Up @@ -215,7 +217,7 @@ boolean onTrackballEvent(MotionEvent event) {
if (currentTrackballLongPressTimeOut != null) {
// Zoom in
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
transform.zoomIn(focalPoint);
mapGestureDetector.zoomInAnimated(focalPoint, true);
}
return true;

Expand Down Expand Up @@ -257,7 +259,7 @@ public void run() {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
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;
Expand Down Expand Up @@ -177,12 +176,12 @@ private void initialiseMap() {
// 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));
Expand Down Expand Up @@ -1030,17 +1029,13 @@ public void setGesturesManager(AndroidGesturesManager gesturesManager) {
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;
Expand All @@ -1064,9 +1059,9 @@ private void onZoom(boolean zoomIn, @Nullable PointF focalPoint) {
focalPoint = new PointF(mapWidth / 2, mapHeight / 2);
}
if (zoomIn) {
transform.zoomIn(focalPoint);
mapGestureDetector.zoomInAnimated(focalPoint, true);
} else {
transform.zoomOut(focalPoint);
mapGestureDetector.zoomOutAnimated(focalPoint, true);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,24 +226,8 @@ void setOnCameraChangeListener(@Nullable MapboxMap.OnCameraChangeListener listen
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) {
Expand Down

0 comments on commit c0bb9aa

Please sign in to comment.