From 2fcbd78062552a7fd4471bc0896b79f9888b91e8 Mon Sep 17 00:00:00 2001 From: Pablo Guardiola Date: Wed, 20 Sep 2017 10:15:56 +0200 Subject: [android] hook camera events into compass (#10019) --- .../java/com/mapbox/mapboxsdk/maps/MapView.java | 62 ++++++++++++++++++--- .../java/com/mapbox/mapboxsdk/maps/MapboxMap.java | 18 ++++++- .../mapbox/mapboxsdk/maps/widgets/CompassView.java | 63 ++++++---------------- 3 files changed, 90 insertions(+), 53 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 4d6189ddcf..149a9fbaa2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -47,6 +47,9 @@ import java.util.concurrent.CopyOnWriteArrayList; import timber.log.Timber; +import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION; +import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_WAIT_IDLE; + /** *

* A {@code MapView} provides an embeddable map interface. @@ -73,6 +76,7 @@ public class MapView extends FrameLayout { private MyLocationView myLocationView; private CompassView compassView; + private PointF focalPoint; private ImageView attrView; private ImageView logoView; @@ -143,7 +147,7 @@ public class MapView extends FrameLayout { addOnMapChangedListener(mapCallback); // callback for focal point invalidation - FocalPointInvalidator focalPoint = new FocalPointInvalidator(compassView); + final FocalPointInvalidator focalPointInvalidator = new FocalPointInvalidator(createFocalPointChangeListener()); // callback for registering touch listeners RegisterTouchListener registerTouchListener = new RegisterTouchListener(); @@ -152,13 +156,15 @@ public class MapView extends FrameLayout { CameraZoomInvalidator zoomInvalidator = new CameraZoomInvalidator(); // callback for camera change events - CameraChangeDispatcher cameraChangeDispatcher = new CameraChangeDispatcher(); + final CameraChangeDispatcher cameraChangeDispatcher = new CameraChangeDispatcher(); // setup components for MapboxMap creation Projection proj = new Projection(nativeMapView); - UiSettings uiSettings = new UiSettings(proj, focalPoint, compassView, attrView, logoView); - TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPoint, zoomInvalidator); - MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, proj, focalPoint); + UiSettings uiSettings = new UiSettings(proj, focalPointInvalidator, compassView, attrView, logoView); + TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPointInvalidator, + zoomInvalidator); + MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, proj, + focalPointInvalidator); LongSparseArray annotationsArray = new LongSparseArray<>(); MarkerViewManager markerViewManager = new MarkerViewManager((ViewGroup) findViewById(R.id.markerViewContainer)); IconManager iconManager = new IconManager(nativeMapView); @@ -182,8 +188,9 @@ public class MapView extends FrameLayout { MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform); mapZoomButtonController.bind(uiSettings, zoomListener); + compassView.injectCompassAnimationListener(createCompassAnimationListener(cameraChangeDispatcher)); + compassView.setOnClickListener(createCompassClickListener(cameraChangeDispatcher)); // inject widgets with MapboxMap - compassView.setMapboxMap(mapboxMap); myLocationView.setMapboxMap(mapboxMap); attrView.setOnClickListener(new AttributionDialogManager(context, mapboxMap)); @@ -205,6 +212,49 @@ public class MapView extends FrameLayout { } } + private FocalPointChangeListener createFocalPointChangeListener() { + return new FocalPointChangeListener() { + @Override + public void onFocalPointChanged(PointF pointF) { + focalPoint = pointF; + } + }; + } + + private MapboxMap.OnCompassAnimationListener createCompassAnimationListener(final CameraChangeDispatcher + cameraChangeDispatcher) { + return new MapboxMap.OnCompassAnimationListener() { + @Override + public void onCompassAnimation() { + cameraChangeDispatcher.onCameraMove(); + } + + @Override + public void onCompassAnimationFinished() { + compassView.isAnimating(false); + cameraChangeDispatcher.onCameraIdle(); + } + }; + } + + private OnClickListener createCompassClickListener(final CameraChangeDispatcher cameraChangeDispatcher) { + return new OnClickListener() { + @Override + public void onClick(View v) { + if (mapboxMap != null && compassView != null) { + if (focalPoint != null) { + mapboxMap.setFocalBearing(0, focalPoint.x, focalPoint.y, TIME_MAP_NORTH_ANIMATION); + } else { + mapboxMap.setFocalBearing(0, mapboxMap.getWidth() / 2, mapboxMap.getHeight() / 2, TIME_MAP_NORTH_ANIMATION); + } + cameraChangeDispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_ANIMATION); + compassView.isAnimating(true); + compassView.postDelayed(compassView, TIME_WAIT_IDLE + TIME_MAP_NORTH_ANIMATION); + } + } + }; + } + // // Lifecycle events // diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java index 0d1d0e03b5..6c7670b91c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java @@ -513,8 +513,9 @@ public final class MapboxMap { * Sets the maximum zoom level the map can be displayed at. *

*

- * The default maximum zoomn level is 22. The upper bound for this value is 25.5. + * The default maximum zoomn level is 22. The upper bound for this value is 25.5. *

+ * * @param maxZoom The new maximum zoom level. */ public void setMaxZoomPreference(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, @@ -2081,6 +2082,21 @@ public final class MapboxMap { void onCameraIdle(); } + /** + * Interface definition for a callback to be invoked for when the compass is animating. + */ + public interface OnCompassAnimationListener { + /** + * Called repeatedly as the compass continues to move after clicking on it. + */ + void onCompassAnimation(); + + /** + * Called when compass animation has ended. + */ + void onCompassAnimationFinished(); + } + /** * Interface definition for a callback to be invoked when a frame is rendered to the map view. * diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java index 2b327409ae..45f72af1c5 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java @@ -1,10 +1,8 @@ package com.mapbox.mapboxsdk.maps.widgets; import android.content.Context; -import android.graphics.PointF; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPropertyAnimatorCompat; import android.support.v4.view.ViewPropertyAnimatorListenerAdapter; @@ -13,11 +11,8 @@ import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; -import com.mapbox.mapboxsdk.maps.FocalPointChangeListener; import com.mapbox.mapboxsdk.maps.MapboxMap; -import java.lang.ref.WeakReference; - /** * UI element overlaid on a map to show the map's bearing when it isn't true north (0.0). Tapping * the compass resets the bearing to true north and hides the compass. @@ -27,16 +22,17 @@ import java.lang.ref.WeakReference; * use {@link com.mapbox.mapboxsdk.maps.UiSettings}. *

*/ -public final class CompassView extends AppCompatImageView implements Runnable, FocalPointChangeListener { +public final class CompassView extends AppCompatImageView implements Runnable { - private static final long TIME_WAIT_IDLE = 500; + public static final long TIME_WAIT_IDLE = 500; + public static final long TIME_MAP_NORTH_ANIMATION = 150; private static final long TIME_FADE_ANIMATION = TIME_WAIT_IDLE; - private static final long TIME_MAP_NORTH_ANIMATION = 150; private float rotation = 0.0f; private boolean fadeCompassViewFacingNorth = true; private ViewPropertyAnimatorCompat fadeAnimator; - private PointF focalPoint; + private MapboxMap.OnCompassAnimationListener compassAnimationListener; + private boolean isAnimating = false; public CompassView(Context context) { super(context); @@ -62,9 +58,12 @@ public final class CompassView extends AppCompatImageView implements Runnable, F setLayoutParams(lp); } - // TODO refactor MapboxMap and replace with interface - public void setMapboxMap(@NonNull MapboxMap mapboxMap) { - setOnClickListener(new CompassClickListener(mapboxMap, this)); + public void injectCompassAnimationListener(@NonNull MapboxMap.OnCompassAnimationListener compassAnimationListener) { + this.compassAnimationListener = compassAnimationListener; + } + + public void isAnimating(boolean isAnimating) { + this.isAnimating = isAnimating; } private void resetAnimation() { @@ -97,11 +96,6 @@ public final class CompassView extends AppCompatImageView implements Runnable, F } } - @Nullable - PointF getFocalPoint() { - return focalPoint; - } - /** * Updates the direction of the compass. * @@ -126,6 +120,7 @@ public final class CompassView extends AppCompatImageView implements Runnable, F setVisibility(View.VISIBLE); } + notifyCompassAnimationListenerWhenAnimating(); setRotation(rotation); } @@ -157,7 +152,8 @@ public final class CompassView extends AppCompatImageView implements Runnable, F @Override public void run() { - if (isFacingNorth() && fadeCompassViewFacingNorth) { + if (isHidden()) { + compassAnimationListener.onCompassAnimationFinished(); resetAnimation(); setLayerType(View.LAYER_TYPE_HARDWARE, null); fadeAnimator = ViewCompat.animate(CompassView.this).alpha(0.0f).setDuration(TIME_FADE_ANIMATION); @@ -172,34 +168,9 @@ public final class CompassView extends AppCompatImageView implements Runnable, F } } - @Override - public void onFocalPointChanged(PointF pointF) { - focalPoint = pointF; - } - - static class CompassClickListener implements View.OnClickListener { - - private WeakReference mapboxMap; - private WeakReference compassView; - - CompassClickListener(final MapboxMap mapboxMap, CompassView compassView) { - this.mapboxMap = new WeakReference<>(mapboxMap); - this.compassView = new WeakReference<>(compassView); - } - - @Override - public void onClick(View view) { - final MapboxMap mapboxMap = this.mapboxMap.get(); - final CompassView compassView = this.compassView.get(); - if (mapboxMap != null && compassView != null) { - PointF focalPoint = compassView.getFocalPoint(); - if (focalPoint != null) { - mapboxMap.setFocalBearing(0, focalPoint.x, focalPoint.y, TIME_MAP_NORTH_ANIMATION); - } else { - mapboxMap.setFocalBearing(0, mapboxMap.getWidth() / 2, mapboxMap.getHeight() / 2, TIME_MAP_NORTH_ANIMATION); - } - compassView.postDelayed(compassView, TIME_WAIT_IDLE + TIME_MAP_NORTH_ANIMATION); - } + private void notifyCompassAnimationListenerWhenAnimating() { + if (isAnimating) { + compassAnimationListener.onCompassAnimation(); } } } -- cgit v1.2.1