From a68788a2cfb85efe69b0d81672bff7272368494e Mon Sep 17 00:00:00 2001 From: Tobrun Date: Fri, 12 May 2017 20:07:06 +0200 Subject: [PATCH] [android] Release android-v5.1.0-beta.2 (#8976) * [android] url getter on sources * [android] fix ui test filter in makefile * [android] - build SNAPSHOT from release branch (#8958) * [android] - update changelog for 5.1.0-beta.2 * [android] - bump version number * [android] - Camera change listener v2.0 * [core] allow filesource url transform reset * [android] Update attribution wordmark (#8774) * Update wordmark on android * Moved attribution i icon to the right of mapbox word (in mapview preview image) * update padding and margin * [android] update hardcoded branch name * revert version to 5.1.0-SNAPSHOT --- Makefile | 2 +- circle.yml | 2 +- platform/android/CHANGELOG.md | 28 ++++- .../maps/CameraChangeDispatcher.java | 67 ++++++++++++ .../mapboxsdk/maps/MapGestureDetector.java | 39 ++++--- .../com/mapbox/mapboxsdk/maps/MapView.java | 11 +- .../com/mapbox/mapboxsdk/maps/MapboxMap.java | 100 +++++++++++++++++- .../mapboxsdk/maps/MapboxMapOptions.java | 30 +++--- .../com/mapbox/mapboxsdk/maps/Transform.java | 57 ++++++++-- .../com/mapbox/mapboxsdk/maps/UiSettings.java | 23 ++-- .../style/sources/GeoJsonSource.java | 10 ++ .../mapboxsdk/style/sources/RasterSource.java | 13 +++ .../mapboxsdk/style/sources/VectorSource.java | 10 ++ .../res/drawable-hdpi/mapbox_logo_icon.png | Bin 3408 -> 4778 bytes .../res/drawable-mdpi/mapbox_logo_icon.png | Bin 1958 -> 2622 bytes .../res/drawable-xhdpi/mapbox_logo_icon.png | Bin 4492 -> 6579 bytes .../res/drawable-xxhdpi/mapbox_logo_icon.png | Bin 7059 -> 10802 bytes .../res/drawable-xxxhdpi/mapbox_logo_icon.png | Bin 9402 -> 14441 bytes .../res/drawable/mapbox_info_icon_default.xml | 8 +- .../drawable/mapbox_info_icon_selected.xml | 10 +- .../res/layout/mapbox_mapview_internal.xml | 3 +- .../res/layout/mapbox_mapview_preview.xml | 35 +++--- .../src/main/res/values/dimens.xml | 9 +- .../testapp/style/RuntimeStyleTests.java | 33 ++++++ .../camera/CameraPositionActivity.java | 31 +++++- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../src/style/sources/geojson_source.cpp | 6 ++ .../src/style/sources/geojson_source.hpp | 2 + .../src/style/sources/raster_source.cpp | 8 +- .../src/style/sources/raster_source.hpp | 2 + .../src/style/sources/vector_source.cpp | 8 +- .../src/style/sources/vector_source.hpp | 2 + platform/default/default_file_source.cpp | 16 +-- 33 files changed, 468 insertions(+), 99 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java diff --git a/Makefile b/Makefile index e8f7f175ff5..abccb306a6a 100644 --- a/Makefile +++ b/Makefile @@ -571,7 +571,7 @@ run-android-ui-test-$1: platform/android/configuration.gradle run-android-ui-test-$1-%: platform/android/configuration.gradle adb uninstall com.mapbox.mapboxsdk.testapp > /dev/null - cd platform/android && $(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 :MapboxGLAndroidSDKTestApp:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class="$*" + cd platform/android && $(MBGL_ANDROID_GRADLE) -Pmapbox.abis=$2 :MapboxGLAndroidSDKTestApp:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class="$$*" endef diff --git a/circle.yml b/circle.yml index 7d75427bcb5..4ce00872b4f 100644 --- a/circle.yml +++ b/circle.yml @@ -133,4 +133,4 @@ jobs: - deploy: name: Publish to Maven command: | - if [ "${CIRCLE_BRANCH}" == "master" ]; then make run-android-upload-archives ; fi + if [ "${CIRCLE_BRANCH}" == "release-android-v5.1.0-beta.2" ]; then make run-android-upload-archives ; fi diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index fdc6343b7c6..bc307e50614 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -3,11 +3,35 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. ## 5.1.0 - TBA - +* Update attribution with new Mapbox wordmark [#8774](https://github.com/mapbox/mapbox-gl-native/pull/8774) + +## 5.1.0-beta.2 - May 12, 2017 + +5.1.0-beta.2 builds further on 5.1.0-beta.1 and adds: + +* When a layer is added, reload its source's tiles [#8963](https://github.com/mapbox/mapbox-gl-native/pull/8963) +* Update release script to support CircleCI builds [#8950](https://github.com/mapbox/mapbox-gl-native/pull/8950) +* URL getter on Sources [#8959](https://github.com/mapbox/mapbox-gl-native/pull/8959) +* Build SNAPSHOT from release branch CI configuration [#8958](https://github.com/mapbox/mapbox-gl-native/pull/8958) +* Fix UI test filter in Makefile [#8960](https://github.com/mapbox/mapbox-gl-native/pull/8960) +* Bump & fixup dependencies [#8921](https://github.com/mapbox/mapbox-gl-native/pull/8921) +* Ignore already deleted region [#8920](https://github.com/mapbox/mapbox-gl-native/pull/8920) +* Keep offline observer when timeout occurs [#8919](https://github.com/mapbox/mapbox-gl-native/pull/8919) +* Show error message when no browser installed [#8920](https://github.com/mapbox/mapbox-gl-native/pull/8920) +* Reset observers of removed Sources and Layers [#8900](https://github.com/mapbox/mapbox-gl-native/pull/8900) +* Only build custom layer .so for debug builds [#8885](https://github.com/mapbox/mapbox-gl-native/pull/8885) +* Update localizations [#8883](https://github.com/mapbox/mapbox-gl-native/pull/8883) +* Reset observers of removed Sources and Layers [#8862](https://github.com/mapbox/mapbox-gl-native/pull/8862) +* Remove force style cascade [#8866](https://github.com/mapbox/mapbox-gl-native/pull/8866) +* Update proguard config [#8944](https://github.com/mapbox/mapbox-gl-native/pull/8944) +* Update LOST to 2.3.0-SNAPSHOT [#8872](https://github.com/mapbox/mapbox-gl-native/pull/8872) +* Update logo [#8774](https://github.com/mapbox/mapbox-gl-native/pull/8774) +* Camera change listener v2.0 [#8644](https://github.com/mapbox/mapbox-gl-native/pull/8644) +* Allow filesource url transform reset [#8957](https://github.com/mapbox/mapbox-gl-native/pull/8957) ## 5.1.0-beta.1 - May 2, 2017 -5.1.0 builds further on 5.0.2 and adds: +5.1.0-beta.1 builds further on 5.0.2 and adds: * Support for FillExtrusionLayer [#8431](https://github.com/mapbox/mapbox-gl-native/pull/8431) * Limit Viewport [#8622](https://github.com/mapbox/mapbox-gl-native/pull/8622) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java new file mode 100644 index 00000000000..bd028aecb6d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java @@ -0,0 +1,67 @@ +package com.mapbox.mapboxsdk.maps; + +import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraIdleListener; +import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveCanceledListener; +import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener; +import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveListener; + +class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, MapboxMap.OnCameraMoveListener, + MapboxMap.OnCameraMoveCanceledListener, OnCameraIdleListener { + + private boolean idle = true; + + private OnCameraMoveStartedListener onCameraMoveStartedListener; + private OnCameraMoveCanceledListener onCameraMoveCanceledListener; + private OnCameraMoveListener onCameraMoveListener; + private OnCameraIdleListener onCameraIdleListener; + + void setOnCameraMoveStartedListener(OnCameraMoveStartedListener onCameraMoveStartedListener) { + this.onCameraMoveStartedListener = onCameraMoveStartedListener; + } + + void setOnCameraMoveCanceledListener(OnCameraMoveCanceledListener onCameraMoveCanceledListener) { + this.onCameraMoveCanceledListener = onCameraMoveCanceledListener; + } + + void setOnCameraMoveListener(OnCameraMoveListener onCameraMoveListener) { + this.onCameraMoveListener = onCameraMoveListener; + } + + void setOnCameraIdleListener(OnCameraIdleListener onCameraIdleListener) { + this.onCameraIdleListener = onCameraIdleListener; + } + + @Override + public void onCameraMoveStarted(int reason) { + if (!idle) { + return; + } + + idle = false; + if (onCameraMoveStartedListener != null) { + onCameraMoveStartedListener.onCameraMoveStarted(reason); + } + } + + @Override + public void onCameraMove() { + if (onCameraMoveListener != null && !idle) { + onCameraMoveListener.onCameraMove(); + } + } + + @Override + public void onCameraMoveCanceled() { + if (onCameraMoveCanceledListener != null && !idle) { + onCameraMoveCanceledListener.onCameraMoveCanceled(); + } + } + + @Override + public void onCameraIdle() { + if (onCameraIdleListener != null && !idle) { + idle = true; + onCameraIdleListener.onCameraIdle(); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java index dca833bbf48..39433d8b933 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java @@ -22,6 +22,8 @@ import com.mapbox.services.android.telemetry.utils.MathUtils; import com.mapbox.services.android.telemetry.utils.TelemetryUtils; +import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE; + /** * Manages gestures events on a MapView. *

@@ -35,6 +37,7 @@ final class MapGestureDetector { private final UiSettings uiSettings; private final TrackingSettings trackingSettings; private final AnnotationManager annotationManager; + private final CameraChangeDispatcher cameraChangeDispatcher; private final GestureDetectorCompat gestureDetector; private final ScaleGestureDetector scaleGestureDetector; @@ -56,12 +59,14 @@ final class MapGestureDetector { private boolean scaleGestureOccurred = false; MapGestureDetector(Context context, Transform transform, Projection projection, UiSettings uiSettings, - TrackingSettings trackingSettings, AnnotationManager annotationManager) { + TrackingSettings trackingSettings, AnnotationManager annotationManager, + CameraChangeDispatcher cameraChangeDispatcher) { this.annotationManager = annotationManager; this.transform = transform; this.projection = projection; this.uiSettings = uiSettings; this.trackingSettings = trackingSettings; + this.cameraChangeDispatcher = cameraChangeDispatcher; // Touch gesture detectors gestureDetector = new GestureDetectorCompat(context, new GestureListener()); @@ -187,6 +192,7 @@ boolean onTouchEvent(@NonNull MotionEvent event) { MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapDragEndEvent( getLocationFromGesture(event.getX(), event.getY()), transform)); scrollInProgress = false; + cameraChangeDispatcher.onCameraIdle(); } twoTap = false; @@ -273,6 +279,9 @@ public boolean onDoubleTapEvent(MotionEvent e) { break; } + // notify camera change listener + cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); + // Single finger double tap if (focalPoint != null) { // User provided focal point @@ -337,6 +346,7 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve // and ignore when a scale gesture has occurred return false; } + cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); float screenDensity = uiSettings.getPixelRatio(); @@ -362,9 +372,7 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve long animationTime = (long) (velocityXY / 7 / tiltFactor + MapboxConstants.ANIMATION_DURATION_FLING_BASE); // update transformation - transform.setGestureInProgress(true); transform.moveBy(offsetX, offsetY, animationTime); - transform.setGestureInProgress(false); if (onFlingListener != null) { onFlingListener.onFling(); @@ -377,6 +385,10 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (!scrollInProgress) { scrollInProgress = true; + + // Cancel any animation + transform.cancelTransitions(); + cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapClickEvent( getLocationFromGesture(e1.getX(), e1.getY()), MapboxEvent.GESTURE_PAN_START, transform)); @@ -391,8 +403,6 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d // reset tracking if needed trackingSettings.resetTrackingModesIfRequired(true, false); - // Cancel any animation - transform.cancelTransitions(); // Scroll the map transform.moveBy(-distanceX, -distanceY, 0 /*no duration*/); @@ -446,6 +456,8 @@ public boolean onScale(ScaleGestureDetector detector) { // If scale is large enough ignore a tap scaleFactor *= detector.getScaleFactor(); if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) { + // notify camera change listener + cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); zoomStarted = true; } @@ -465,9 +477,6 @@ public boolean onScale(ScaleGestureDetector detector) { return false; } - // Cancel any animation - transform.cancelTransitions(); - // Gesture is a quickzoom if there aren't two fingers quickZoom = !twoTap; @@ -512,6 +521,9 @@ public boolean onRotateBegin(RotateGestureDetector detector) { return false; } + // notify camera change listener + cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); + beginTime = detector.getEventTime(); MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapClickEvent( getLocationFromGesture(detector.getFocusX(), detector.getFocusY()), @@ -522,6 +534,7 @@ public boolean onRotateBegin(RotateGestureDetector detector) { // Called when the fingers leave the screen @Override public void onRotateEnd(RotateGestureDetector detector) { + // notify camera change listener beginTime = 0; totalAngle = 0.0f; started = false; @@ -553,13 +566,8 @@ public boolean onRotate(RotateGestureDetector detector) { if (!started) { return false; } - - // Cancel any animation - transform.cancelTransitions(); - // rotation constitutes translation of anything except the center of // rotation, so cancel both location and bearing tracking if required - trackingSettings.resetTrackingModesIfRequired(true, true); // Get rotate value @@ -593,6 +601,8 @@ public boolean onShoveBegin(ShoveGestureDetector detector) { return false; } + // notify camera change listener + cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); beginTime = detector.getEventTime(); MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapClickEvent( getLocationFromGesture(detector.getFocusX(), detector.getFocusY()), @@ -633,9 +643,6 @@ public boolean onShove(ShoveGestureDetector detector) { return false; } - // Cancel any animation - transform.cancelTransitions(); - // Get tilt value (scale and clamp) double pitch = transform.getTilt(); pitch -= 0.1 * detector.getShovePixelsDelta(); 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 872802292c4..d00da4c155d 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 @@ -129,6 +129,9 @@ private void initialise(@NonNull final Context context, @NonNull final MapboxMap // callback for zooming in the camera CameraZoomInvalidator zoomInvalidator = new CameraZoomInvalidator(); + // callback for camera change events + CameraChangeDispatcher cameraChangeDispatcher = new CameraChangeDispatcher(); + // setup components for MapboxMap creation Projection proj = new Projection(nativeMapView); UiSettings uiSettings = new UiSettings(proj, focalPoint, compassView, attrView, view.findViewById(R.id.logoView)); @@ -136,12 +139,14 @@ private void initialise(@NonNull final Context context, @NonNull final MapboxMap MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, proj, focalPoint); MarkerViewManager markerViewManager = new MarkerViewManager((ViewGroup) findViewById(R.id.markerViewContainer)); AnnotationManager annotations = new AnnotationManager(nativeMapView, this, markerViewManager); - Transform transform = new Transform(nativeMapView, annotations.getMarkerViewManager(), trackingSettings); + Transform transform = new Transform(nativeMapView, annotations.getMarkerViewManager(), trackingSettings, + cameraChangeDispatcher); mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, proj, - registerTouchListener, annotations); + registerTouchListener, annotations, cameraChangeDispatcher); // user input - mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings, annotations); + mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings, annotations, + cameraChangeDispatcher); mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings); MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform); 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 1751dcf0428..96603355f19 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 @@ -69,6 +69,7 @@ public final class MapboxMap { private final Transform transform; private final AnnotationManager annotationManager; private final MyLocationViewSettings myLocationViewSettings; + private final CameraChangeDispatcher cameraChangeDispatcher; private final OnRegisterTouchListener onRegisterTouchListener; @@ -76,7 +77,7 @@ public final class MapboxMap { MapboxMap(NativeMapView map, Transform transform, UiSettings ui, TrackingSettings tracking, MyLocationViewSettings myLocationView, Projection projection, OnRegisterTouchListener listener, - AnnotationManager annotations) { + AnnotationManager annotations, CameraChangeDispatcher cameraChangeDispatcher) { this.nativeMapView = map; this.uiSettings = ui; this.trackingSettings = tracking; @@ -85,6 +86,7 @@ public final class MapboxMap { this.annotationManager = annotations.bind(this); this.transform = transform; this.onRegisterTouchListener = listener; + this.cameraChangeDispatcher = cameraChangeDispatcher; } void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) { @@ -1595,10 +1597,51 @@ public int[] getPadding() { * To unset the callback, use null. */ @UiThread + @Deprecated public void setOnCameraChangeListener(@Nullable OnCameraChangeListener listener) { transform.setOnCameraChangeListener(listener); } + /** + * Sets a callback that is invoked when camera movement has ended. + * + * @param listener the listener to notify + */ + @UiThread + public void setOnCameraIdleListener(@Nullable OnCameraIdleListener listener) { + cameraChangeDispatcher.setOnCameraIdleListener(listener); + } + + /** + * Sets a callback that is invoked when camera movement was cancelled. + * + * @param listener the listener to notify + */ + @UiThread + public void setOnCameraMoveCancelListener(@Nullable OnCameraMoveCanceledListener listener) { + cameraChangeDispatcher.setOnCameraMoveCanceledListener(listener); + } + + /** + * Sets a callback that is invoked when camera movement has started. + * + * @param listener the listener to notify + */ + @UiThread + public void setOnCameraMoveStartedistener(@Nullable OnCameraMoveStartedListener listener) { + cameraChangeDispatcher.setOnCameraMoveStartedListener(listener); + } + + /** + * Sets a callback that is invoked when camera position changes. + * + * @param listener the listener to notify + */ + @UiThread + public void setOnCameraMoveListener(@Nullable OnCameraMoveListener listener) { + cameraChangeDispatcher.setOnCameraMoveListener(listener); + } + /** * Sets a callback that's invoked on every frame rendered to the map view. * @@ -1913,7 +1956,12 @@ public interface OnScrollListener { /** * Interface definition for a callback to be invoked when the camera changes position. + * + * @deprecated Replaced by MapboxMap.OnCameraMoveStartedListener, MapboxMap.OnCameraMoveListener and + * MapboxMap.OnCameraIdleListener. The order in which the deprecated onCameraChange method will be called in relation + * to the methods in the new camera change listeners is undefined. */ + @Deprecated public interface OnCameraChangeListener { /** * Called after the camera position has changed. During an animation, @@ -1925,6 +1973,56 @@ public interface OnCameraChangeListener { void onCameraChange(CameraPosition position); } + /** + * Interface definition for a callback to be invoked for when the camera motion starts. + */ + public interface OnCameraMoveStartedListener { + int REASON_API_GESTURE = 1; + int REASON_DEVELOPER_ANIMATION = 2; + int REASON_API_ANIMATION = 3; + + /** + * Called when the camera starts moving after it has been idle or when the reason for camera motion has changed. + * + * @param reason the reason for the camera change + */ + void onCameraMoveStarted(int reason); + } + + /** + * Interface definition for a callback to be invoked for when the camera changes position. + */ + public interface OnCameraMoveListener { + /** + * Called repeatedly as the camera continues to move after an onCameraMoveStarted call. + * This may be called as often as once every frame and should not perform expensive operations. + */ + void onCameraMove(); + } + + /** + * Interface definition for a callback to be invoked for when the camera's motion has been stopped or when the camera + * starts moving for a new reason. + */ + public interface OnCameraMoveCanceledListener { + /** + * Called when the developer explicitly calls the cancelTransitions() method or if the reason for camera motion has + * changed before the onCameraIdle had a chance to fire after the previous animation. + * Do not update or animate the camera from within this method. + */ + void onCameraMoveCanceled(); + } + + /** + * Interface definition for a callback to be invoked for when camera movement has ended. + */ + public interface OnCameraIdleListener { + /** + * Called when camera movement has ended. + */ + void onCameraIdle(); + } + /** * 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/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java index 8fcfdd6db0b..68603ab1a38 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java @@ -35,10 +35,8 @@ */ public class MapboxMapOptions implements Parcelable { - private static final float DIMENSION_SEVEN_DP = 7f; - private static final float DIMENSION_TEN_DP = 10f; - private static final float DIMENSION_SIXTEEN_DP = 16f; - private static final float DIMENSION_SEVENTY_SIX_DP = 76f; + private static final float FOUR_DP = 4f; + private static final float EIGHTY_NINE_DP = 92f; private CameraPosition cameraPosition; @@ -206,13 +204,13 @@ public static MapboxMapOptions createFromAttributes(@NonNull Context context, @N Gravity.TOP | Gravity.END)); mapboxMapOptions.compassMargins(new int[] { (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginLeft, - DIMENSION_TEN_DP * pxlRatio)), + FOUR_DP * pxlRatio)), ((int) typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginTop, - DIMENSION_TEN_DP * pxlRatio)), + FOUR_DP * pxlRatio)), ((int) typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginRight, - DIMENSION_TEN_DP * pxlRatio)), + FOUR_DP * pxlRatio)), ((int) typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginBottom, - DIMENSION_TEN_DP * pxlRatio))}); + FOUR_DP * pxlRatio))}); mapboxMapOptions.compassFadesWhenFacingNorth(typedArray.getBoolean( R.styleable.mapbox_MapView_mapbox_uiCompassFadeFacingNorth, true)); Drawable compassDrawable = typedArray.getDrawable( @@ -227,13 +225,13 @@ public static MapboxMapOptions createFromAttributes(@NonNull Context context, @N Gravity.BOTTOM | Gravity.START)); mapboxMapOptions.logoMargins(new int[] { (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginLeft, - DIMENSION_SIXTEEN_DP * pxlRatio)), + FOUR_DP * pxlRatio)), (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginTop, - DIMENSION_SIXTEEN_DP * pxlRatio)), + FOUR_DP * pxlRatio)), (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginRight, - DIMENSION_SIXTEEN_DP * pxlRatio)), + FOUR_DP * pxlRatio)), (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginBottom, - DIMENSION_SIXTEEN_DP * pxlRatio))}); + FOUR_DP * pxlRatio))}); mapboxMapOptions.attributionTintColor(typedArray.getColor( R.styleable.mapbox_MapView_mapbox_uiAttributionTintColor, -1)); @@ -243,13 +241,13 @@ public static MapboxMapOptions createFromAttributes(@NonNull Context context, @N R.styleable.mapbox_MapView_mapbox_uiAttributionGravity, Gravity.BOTTOM)); mapboxMapOptions.attributionMargins(new int[] { (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginLeft, - DIMENSION_SEVENTY_SIX_DP) * pxlRatio), + EIGHTY_NINE_DP * pxlRatio)), (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginTop, - DIMENSION_SEVEN_DP * pxlRatio)), + FOUR_DP * pxlRatio)), (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginRight, - DIMENSION_SEVEN_DP * pxlRatio)), + FOUR_DP * pxlRatio)), (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginBottom, - DIMENSION_SEVEN_DP * pxlRatio))}); + FOUR_DP * pxlRatio))}); mapboxMapOptions.locationEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_myLocation, false)); mapboxMapOptions.myLocationForegroundTintColor( diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java index e101340111b..af44a08a814 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java @@ -16,6 +16,7 @@ import timber.log.Timber; import static com.mapbox.mapboxsdk.maps.MapView.REGION_DID_CHANGE_ANIMATED; +import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveStartedListener; /** * Resembles the current Map transformation. @@ -33,13 +34,18 @@ final class Transform implements MapView.OnMapChangedListener { private CameraPosition cameraPosition; private MapboxMap.CancelableCallback cameraCancelableCallback; + private MapboxMap.OnCameraChangeListener onCameraChangeListener; - Transform(NativeMapView mapView, MarkerViewManager markerViewManager, TrackingSettings trackingSettings) { + private CameraChangeDispatcher cameraChangeDispatcher; + + Transform(NativeMapView mapView, MarkerViewManager markerViewManager, TrackingSettings trackingSettings, + CameraChangeDispatcher cameraChangeDispatcher) { this.mapView = mapView; this.markerViewManager = markerViewManager; this.trackingSettings = trackingSettings; this.myLocationView = trackingSettings.getMyLocationView(); + this.cameraChangeDispatcher = cameraChangeDispatcher; } void initialise(@NonNull MapboxMap mapboxMap, @NonNull MapboxMapOptions options) { @@ -79,6 +85,7 @@ public void onMapChanged(@MapView.MapChange int change) { cameraCancelableCallback.onFinish(); cameraCancelableCallback = null; } + cameraChangeDispatcher.onCameraIdle(); mapView.removeOnMapChangedListener(this); } } @@ -89,10 +96,12 @@ final void moveCamera(MapboxMap mapboxMap, CameraUpdate update, MapboxMap.Cancel if (!cameraPosition.equals(this.cameraPosition)) { trackingSettings.resetTrackingModesIfRequired(cameraPosition); cancelTransitions(); + cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION); mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom); if (callback != null) { callback.onFinish(); } + cameraChangeDispatcher.onCameraIdle(); } } @@ -103,6 +112,8 @@ final void easeCamera(MapboxMap mapboxMap, CameraUpdate update, int durationMs, if (!cameraPosition.equals(this.cameraPosition)) { trackingSettings.resetTrackingModesIfRequired(cameraPosition); cancelTransitions(); + cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION); + if (callback != null) { cameraCancelableCallback = callback; mapView.addOnMapChangedListener(this); @@ -119,8 +130,9 @@ final void animateCamera(MapboxMap mapboxMap, CameraUpdate update, int durationM CameraPosition cameraPosition = update.getCameraPosition(mapboxMap); if (!cameraPosition.equals(this.cameraPosition)) { trackingSettings.resetTrackingModesIfRequired(cameraPosition); - cancelTransitions(); + cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION); + if (callback != null) { cameraCancelableCallback = callback; mapView.addOnMapChangedListener(this); @@ -135,7 +147,12 @@ final void animateCamera(MapboxMap mapboxMap, CameraUpdate update, int durationM @Nullable CameraPosition invalidateCameraPosition() { if (mapView != null) { - cameraPosition = mapView.getCameraPosition(); + CameraPosition cameraPosition = mapView.getCameraPosition(); + if (this.cameraPosition != null && !this.cameraPosition.equals(cameraPosition)) { + cameraChangeDispatcher.onCameraMove(); + } + + this.cameraPosition = cameraPosition; if (onCameraChangeListener != null) { onCameraChangeListener.onCameraChange(this.cameraPosition); } @@ -144,10 +161,17 @@ CameraPosition invalidateCameraPosition() { } void cancelTransitions() { + // notify user about cancel + cameraChangeDispatcher.onCameraMoveCanceled(); + + // notify animateCamera and easeCamera about cancelling if (cameraCancelableCallback != null) { + cameraChangeDispatcher.onCameraIdle(); cameraCancelableCallback.onCancel(); cameraCancelableCallback = null; } + + // cancel ongoing transitions mapView.cancelTransitions(); } @@ -157,6 +181,10 @@ void resetNorth() { mapView.resetNorth(); } + // + // Camera change listener API + // + void setOnCameraChangeListener(@Nullable MapboxMap.OnCameraChangeListener listener) { this.onCameraChangeListener = listener; } @@ -172,9 +200,6 @@ void setOnCameraChangeListener(@Nullable MapboxMap.OnCameraChangeListener listen } void zoom(boolean zoomIn, @NonNull PointF focalPoint) { - // Cancel any animation - cancelTransitions(); - CameraPosition cameraPosition = invalidateCameraPosition(); if (cameraPosition != null) { int newZoom = (int) Math.round(cameraPosition.zoom + (zoomIn ? 1 : -1)); @@ -187,6 +212,15 @@ void setZoom(double zoom, @NonNull PointF focalPoint) { } void setZoom(double zoom, @NonNull PointF focalPoint, long duration) { + mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() { + @Override + public void onMapChanged(int change) { + if (change == MapView.REGION_DID_CHANGE_ANIMATED) { + mapView.removeOnMapChangedListener(this); + cameraChangeDispatcher.onCameraIdle(); + } + } + }); mapView.setZoom(zoom, focalPoint, duration); } @@ -278,6 +312,17 @@ void zoomBy(double z, float x, float y) { } void moveBy(double offsetX, double offsetY, long duration) { + if (duration > 0) { + mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() { + @Override + public void onMapChanged(int change) { + if (change == MapView.DID_FINISH_RENDERING_MAP_FULLY_RENDERED) { + mapView.removeOnMapChangedListener(this); + cameraChangeDispatcher.onCameraIdle(); + } + } + }); + } mapView.moveBy(offsetX, offsetY, duration); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java index 354a42536a3..1bcf8a70b96 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java @@ -146,7 +146,7 @@ private void initialiseCompass(MapboxMapOptions options, Resources resources) { if (compassMargins != null) { setCompassMargins(compassMargins[0], compassMargins[1], compassMargins[2], compassMargins[3]); } else { - int tenDp = (int) resources.getDimension(R.dimen.mapbox_ten_dp); + int tenDp = (int) resources.getDimension(R.dimen.mapbox_four_dp); setCompassMargins(tenDp, tenDp, tenDp, tenDp); } setCompassFadeFacingNorth(options.getCompassFadeFacingNorth()); @@ -171,9 +171,7 @@ private void saveCompass(Bundle outState) { private byte[] convert(Bitmap resource) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); resource.compress(Bitmap.CompressFormat.PNG, 100, stream); - byte[] byteArray = stream.toByteArray(); - - return byteArray; + return stream.toByteArray(); } private void restoreCompass(Bundle savedInstanceState) { @@ -189,10 +187,7 @@ private void restoreCompass(Bundle savedInstanceState) { private Drawable decode(byte[] bitmap) { Bitmap compass = BitmapFactory.decodeByteArray(bitmap, 0, bitmap.length); - - Drawable compassImage = new BitmapDrawable(compassView.getResources(), compass); - - return compassImage; + return new BitmapDrawable(compassView.getResources(), compass); } private void initialiseLogo(MapboxMapOptions options, Resources resources) { @@ -202,8 +197,8 @@ private void initialiseLogo(MapboxMapOptions options, Resources resources) { if (logoMargins != null) { setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]); } else { - int sixteenDp = (int) resources.getDimension(R.dimen.mapbox_sixteen_dp); - setLogoMargins(sixteenDp, sixteenDp, sixteenDp, sixteenDp); + int twoDp = (int) resources.getDimension(R.dimen.mapbox_two_dp); + setLogoMargins(twoDp, twoDp, twoDp, twoDp); } } @@ -226,16 +221,12 @@ private void restoreLogo(Bundle savedInstanceState) { } private void initialiseAttribution(Context context, MapboxMapOptions options) { - Resources resources = context.getResources(); setAttributionEnabled(options.getAttributionEnabled()); setAttributionGravity(options.getAttributionGravity()); int[] attributionMargins = options.getAttributionMargins(); if (attributionMargins != null) { - setAttributionMargins(attributionMargins[0], attributionMargins[1], attributionMargins[2], attributionMargins[3]); - } else { - int sevenDp = (int) resources.getDimension(R.dimen.mapbox_seven_dp); - int seventySixDp = (int) resources.getDimension(R.dimen.mapbox_seventy_six_dp); - setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp); + setAttributionMargins(attributionMargins[0], attributionMargins[1], + attributionMargins[2], attributionMargins[3]); } int attributionTintColor = options.getAttributionTintColor(); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java index ec801867617..10ecb945ad4 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java @@ -227,6 +227,14 @@ public void setUrl(String url) { nativeSetUrl(url); } + /** + * @return The url or null + */ + @Nullable + public String getUrl() { + return nativeGetUrl(); + } + /** * Queries the source for features. * @@ -243,6 +251,8 @@ public List querySourceFeatures(@Nullable Filter.Statement filter) { protected native void nativeSetUrl(String url); + protected native String nativeGetUrl(); + private native void nativeSetGeoJsonString(String geoJson); private native void nativeSetFeatureCollection(FeatureCollection geoJson); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java index 98b74afcffb..38ed2086184 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java @@ -1,5 +1,7 @@ package com.mapbox.mapboxsdk.style.sources; +import android.support.annotation.Nullable; + import java.net.URL; /** @@ -72,8 +74,19 @@ public RasterSource(String id, TileSet tileSet, int tileSize) { initialize(id, tileSet.toValueObject(), tileSize); } + /** + * @return The url or null + */ + @Nullable + public String getUrl() { + return nativeGetUrl(); + } + protected native void initialize(String layerId, Object payload, int tileSize); @Override protected native void finalize() throws Throwable; + + protected native String nativeGetUrl(); + } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java index 7230492d0e9..9b59cf8967d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java @@ -76,11 +76,21 @@ public List querySourceFeatures(@Size(min = 1) String[] sourceLayerIds, return features != null ? Arrays.asList(features) : new ArrayList(); } + /** + * @return The url or null + */ + @Nullable + public String getUrl() { + return nativeGetUrl(); + } + protected native void initialize(String layerId, Object payload); @Override protected native void finalize() throws Throwable; + protected native String nativeGetUrl(); + private native Feature[] querySourceFeatures(String[] sourceLayerId, Object[] filter); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_logo_icon.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/mapbox_logo_icon.png index c0f4ed2c4ccea49c85cea67dfdbbe73093e6aed2..7568387a8da1c702981dd72c9a154e278a7436ca 100644 GIT binary patch literal 4778 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 Ef@lR+_y7O^ literal 3408 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 literal 1958 zcmV;X2U+-uP)fd(ofB(zNMk49Xeq6EmKHg(DPkz!zyVl8E4t@TnU?Y+CV z=hA!Id#<-Tyu7?;Gcq!=9IB}k zl>^KI<^qL0INAVD0L6|`q;x(r&K5q49U@t2-eq8i?QAvjm28TdR|rgZ_?R<>JgxB$ z(cj;HqoAPR*|TTQt}ZPtJ-unurY9FJTv(y&dS7N{rgQU|*hkrYA_VXQ_kk~rv5WwH zW4xQCh6&sOdX#=1Fptp$Ca_Pe^W%mAA9ff|aLD_B&UA~82#13Q4{jSC9*!D@F<4$+ zzS{5iUl9>Ge*F0Bx~}&*!eLoqVd2->+S=+9iG(I15|76}xOVN@?{afCX;c)FoxEyUHdIy(HO*!Bw^dO zZI$QGpFbobGB7aEAtDk81g-&ICkffv*=2se|6LIg!!V+nrnMV}5fc%)bLY-GY9n6L zG!uql3m zibkWiBaz6zMZ_{qbNJ}dqd&^d&Mwn5txZIvsj2DL9*<|arfD}tL>d|zeyQwC``9FS zJf7uh5wR@G*t&J=cikkMIC0`?<=-shn$M@p#cu+*lojZ4~^LRYVW3gDDWm#r@ef_SKUR_9Gh%O9J3Mbm-7F5wULGym>0M zsFQ@QuCBj`h^R{PW$c)J{@Af&KNS&aZ*Tu&8WQFLFC0F6_=h4Q9UUESr6FM^u&kk> zp;|Poon6?l(6#cLC()=H?d_6%_#V_V)VJUV4CDz_@$&t`DH7sAxLC#*G`_ zF$`l6psTCv!o`ahBiISi`lKX;foMrd$s5nhK7cc zC&Y|0Fg*U^Z9%sfLXI<6=P@n)Jd2)d-m*NfbQ<@ zet@Q?rteRjIPoz+=FgwMs;a8$Y3$NGqN;ox5(KybypP=(#@z~6uU@?Zux{PDSC=eV zG84NTP5%hHb1Nz;o?5eJ%@%+Q7cMlX(OIy5{rcJE<>l)EIeq$c^WMFC-`91$Z_b=K zU#+jNUxppupR22@d%n21_@#I}9;mLazExXWyQrk3gSo6nORj;Rj(Ho z7EZ=4=jpBtK>D1pz@;+-S5C;v$}02w{a00H9}I;;t-)ZhB@_y^sS0rcS9Q=dtv#7c zrm90KzDHCCRY8VDMB3Wg{=n$!Akk>FI~t9Ss1A!3E&7J8>jBHMl6&^-c@^+>c6Odq z`RPwQ$R&@C1XQ2U+S+8_1t$qkc`O#|xqSKZZ^r5qM8u3nqrS$*#$Ty*=3#e+ zrMq_R+7Ji?-Zf1#VVdS}Fc@q}IqdWKnp7e^rsh32Z{EC@W3kvh5ix6PYqtY0rW|q~ zi40&dBQHo@z&*!v4t51dg^~cR*m3#9SnL9rrulXx66wmz%iH1*3wB~lFm~y3cZ|~% zA=xfH1G@`$`qiW6J_k&8$OnLb!sxbHu;c!5htUC-P8?{#?$N=%O6%C!z8kwdPI7JJ zF-A8hA1K>lYyvWrvrfk>wVnnf9rF9Y-<8cNYHm!~n!VR~BAJD$h8L!^VK`C*rQNDViV*#C`;!nhZxM~FDUgb5Q~QqMw~ sD)VV!%rfymz;x`eNF7CYn0;#aFXeA|gUDnK2><{907*qoM6N<$f(Q%0c>n+a diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_logo_icon.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/mapbox_logo_icon.png index 194aa64da214388eec2e2449cf35d57a4d0fbed9..7eec45f4b199ffffb46c4274a7c5973127d084ba 100644 GIT binary patch literal 6579 zcmV;k8BFGhP)k{d7jDkIlHs7v$L~%lOy!U zAc5xPz#?FN2Z@IEI+#j)1Go*$hHMUGnFBep+#(c`a8?B+partneh>8}u&cmqq0J)m z{>|01BB%vnR9&!AB*R*^Y#D#@$tM@6T)A?5g$fl4t9;$Mbvu)jlXov&x^&NX-+i|` zvJL4q-~w=0Kv{NHHV48ukQqVEMT>f14KSx#=g*%%$DMcHc~XZC9qQDtU%zpI0tHGc zKN{@WvuE?XdGlrt88T$?z<~od@7=ris8{z0;R;X!d)Uj%4zf9rjsqD9s_f3DU~${> z<(FTsbnm_QUR}6w;j%U_E8(tPyMBG=op*-z=+Q$O)xs7cQ^9>UBRkA82ddLT$|T-t zshw;knCRsFEu*mnRko;v)Yzdn-E>pJE3drLu2iW~wNJ!IH*em&yldC4Uw`t+CtE#w zvR|iw+fM}je;JJ`jQ6YK<1flcD;@rJC?ik)?070%{FY<@a9ubJ++o}R=qQp#Q#i~GomNbpiMwCu!$2V z{%Jz$ez$4Urfu;INI(VpwoDGA&6SZ2*&K)zRJor@h%Ilu^;QkET$VNIfddD29-5+ZyjinmZTt4^tHXdmeK^g;vj1dr01miYzfOxa#g!XwxFO;G z`|rO)@yx=iRjcN{{`%|RzW@IFoA&M7cf@Vis8OT*k3RZn&9*>XT%2yP0s%ANju|s% z^#1I#&vd}51Q)O8hJpu?ri@K6W<1kw#rI_YHLB?-vH{2AiCuMBKwZ*C!@m0Jt5;?A;DlXy00DikTeogWA{Yd- zXV2b?&vkyea^)6(^UXJ{PdVk37D4s&O}>34g8Cli>Wj4MjG(&YX;C!RS?$df<9+ z4wzYil>pe?il`AXEi!?4B7Q6YqtVmCsSk=bL7?)=U_(%2n-6Mitw1AFgf3{|O$H_0 z;?+4|&^$`d>J>x3Q?iGzqxS0Jmv*ue$20;w4L#%=hDuKW?2gX;PYZA)!gR5S#)^LkjdgP3$R3 z2%w+y>Z`9VTCG~Of;)HaJowX3Kkb+@WlBaGO5=(Nx>RY?rcIF=HEI;ty?ghepMU;2 zZQ8VHmTq|(mjbnjCA1kre0+S)Yp%H_p=#Bt@m#*v-;w-)hdkyG1Yt*dw3FdagvZL+tC#(R_r))=FCqJ%JnY&)YR13FTM2AW44{> zb6D(m=+L2Lw;pE8vNzs%;|W`juq`OY3eEz}cM;5+5$pkcH_>gc_|~mkr#$=Yvt3n} zaehu;mJ8{F1i`dd*r`*eE_^S^;zJKT^f3LunZ?p~|Ni~U0_aY2#{i9M!Ls0GqQ`FZ zgxlunr=RYjejs+ z&6LMstt;Osqd2!-Dd0|a1Yct+--VGQM}FR}UAwuwLFjRk<IKUl^r~IFfDK1yiePD2wi1v=pMA` z@#Du2MO!s3Sg@e9c~n@oY}vGP&N*ikV?RtKp|n>X1hv{Dk34dpZ8%}Vgs-62f-7#j z&D)}|@RwhHnRNEqXOBmik5X^|90#fojlmGtSJ@@p&f3CSTfT>rPb5Tc|-n41c66E83gjQL-H8jCA2oyw_0SL{AKmuf9)7JLN)VG)dVQFZBt&p

L7~>ITNnP|gAcj{2`S$Uqr(JW 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 literal 7059 zcmW-m2Q(aS7siLxf+!I!YIG7UB7_yaMU77MUJ|{F9ui&nWA#piC0ek03!()!q0tf21(L7d_LUKmW<3(?>twY#jIyQY)1yO)`(73AgR#bf8_;AUaw zY{lc`YLmVTe*i%=B#JVUTHYBuMt+9>Y0uvh5iUzGV})?IlE+7J)Zf!+;L_9E`ckm= zJ*^>Cp|&FV8yo9ZWKxP?^;3OaR`*1Y)A7+7A^oPWNoje}92_pB?_Xh&e%zW}_qi30 z9?DoJ93Z3|I}3Pm_-e>)=sa`XXJ{{D;TSF&+xjir#_40=Fd3+EsSf;;dEY~Elk;?v)Rj5mhh21y`# z6fooIEctp19I;aCGbIU4pF+d2x9QS7IBkp&5?ZnT6&TNlxuTDN@%Op~P*H{%e~2MJ z{_t9{pSq2T#HHtc7o7(!5^d5N@4)-%%dtYDQ$x2`1@c86p;1``zVoi5fE-tQltD`YG>+6PKFWw`8MPVMB z{$y@aEkTE_1rxZh#UH%w?QI-z!`Q4RRzJ{x{`@gHzr1WM9!Aen2%Vhv5X|zia3%66Q~3FZ(0fiT=WFTf7u2~7 z{t?DDIMBzK7?tSA$OQH7P6_w;U?`l*7{O;2vV3;1y#89TT(l)I;3{N<{co)Ti|hF1$L^wfwIk4Vq0?95x!5~j)kZ(bi7h@5> zYAh8-)Kyc4&KVCWR~ejWqqeLY4??8*b*?;y`1J^}8UoGaQ&G#4qmn5CBlAW1nI+vy zx2glwAMlDOJ-I(xd{a6~t)jkn@9*s2)&4lg+4{=aoU>ObSI}n%X^cV@Wk8{xOZYB92tbT%@A`wl_UxGv;BYDX1u)g)D z@CG8QJ*9Hhzq)UXc4Gzy36+2Q_AHfLniO*%m*nnWOq4lR5PT(=F;VP65b@b?AMTtD zmiy5bCL>mxFiDhwQ-qH>39lzh&@0BqG*)K}J_-rp-VXC2DSLt^8}eR1=?MSGKfpg+ z%YyY*oB1qAW1O|aHBn+gpU@pzbB_j`SAQfe$Hc_Qx;Lb!zqYitUh~%6A)*!Lo9gbi zx^EP){5|G&;@2<3XNgS#PoBfP30EWy{IaFuap~`LFhV}_aeI3L`0@DD7T>}inyW5 zALnb9MMIQ-&7UxBbw}eNCVXh2EBrUD@uW>nO)`>_l7F&jvPh4J^hM+6=B5>34|}Cd z6F#y!<4m#b<+Zc~ltx7geiMQc$3}+AOWO5qbLb zNKsy1-szLV3SpaE@tBq}TU8;$8 z7b%p=wN>Z1?`8R9YBgUzE=y5GgLTCzE}2Qfvp`9#GUB@b3z z&(%~^RD^hqo4o&R6Q!%0o5}`0K17MZarXxcV|0h1qNauhrp-{s`PNeBhd4K9XXm== zYBx+MMsAEJrQgBoiT?aZzI>~aq9W&0mq73H)szprvkh)3NF=vY-Py%f#iUyLvmJ4* z13D6yVTGX zgKer|XlU4EfOIUZaCrLQJmb0B8v4?EHAy$1V%%Qaz4_$iWI8A)h!bKwU>k1od>mr0S zZX1ik28f@BzW&r?_;BWh>{8a%4zzejr+K_om-kC)X}?g4qo(FqZB0#$RnhJ`dL*Al zf9IFI$4ryYp)q>XXM4KV0lUXVtq)zG8$&6E7Dmw7#M>MUXNumNvB{nwp?V9jV8FrYQtZa8691hR29zm9uzZkUF zG%*QOWct*V=1W1wri>`p;@bNZFf7`yI-2 zXF7g2x|6oPu~D90JOIwk&tJ)2rp0DvVZofnXV$T`y1Lr8ySrP1S5QYqEmo0}!|3AT za^PoXX69zPnsIP^9P@~S$O+x8G_hA-px#^wo8QT=F(o>*4IrhtHeTZsb8 zpA86Ps<>(v{M=10@g>QpcwiRcMMZ2o>)C-VVJ?baotHXT@7%d_D{ZnUtXgL`R)n0( zZL}UtTRb~E^Lq2<4Qf@X5~Qy07P4+Wa4ppa_3I8QN}k@Q>u@Z&N? zg}*PS166n+UYJz-!E(>S@%}#A(>5AB(dSTH;uay>pN#ol2}w!g^?|oHae8m_^73xJ z+K+#cKwSZ^Q}gllRn6Pq(M4&%>?ED}Ouo#y<>|l9FPAi-~2Ma>hdH znwoAy{ry{X6x^}764@{OFPuQ~OcM5k@?vReX)$hZZzrRrqw`5rjLXQ#;I6E!#8oj8 z2kFrC`SWM&G6#`NRW~3Idj%RBsX%leG#HlO!Na4XB_}6e-P)pgbRR$UR98#u$ja81 z!>RHSFR#hc`uZuM(fq`O4mAZuvitRg2P-s?B{uVRp~XMD((?*@4HA5fiAJ{pMESGR z*gMJt=h_KqN9&mF)5vm5rKFeRPXn&Jv$o$v3^{}IMrAD^s$8O?eu;XIW6f$0|Nf0^ zbl=b@Dyg)xv}CECu5=HF;Sv>8ZEgng^YaUo8#SK9a2oiX?i%&k_k3xz>Q5FD&9Ai? z&hlDy_2Di>%H`X|MMXu~)G8?}XOxa@{3`RTb6QAdV`Cc`OYw#>DhTXlG|funb35R@MX)!Eztp!V#>dy$dl!5GFOzC>ZH45N1r7c+@*EP?q$v z@OJyl{OLmAZR(xsB7MNrRD9M02z~eGJucJH(b50a*Vi)_Df>T3RVJsWZ#it-Ynl0u z0$X!LiKL^90r6oA47_d467%z<+`6c-8>8TJl`QMHIzJp{VPR>SA06!w-~^&E?KIz% zYBP!xl=Miqe0&|)KcBJtgMiqwudc5bcppE$qFk<89M?5j-FXI_ zXQ$C~$ACCIkV{xtIAF5e=+)HJ)Nn&XL(D(9O-r6M3B0a|o~t3UE^0ra7J%By^s8@J zQ~I4!QS%@{Us!yPW}eHfH0um!-`U>w=2z1wao_6*BXAqsu=vvzfeXOsK+I_O&z~o* zeF>~D=BOEBdKd!X)nC4BVj1nC(ZcVpFOK0(O|`=AX!UCvr>07c{E>Z%w49urh0)lb zQ`I(&=VxbKKRwdZ(q4X#V`$969;Iu9ryDGVkd}%EOb7jP=7%nI%cq@__ zD-@1EAY61t?IGqiK4#|S2~ff}k|{IO(~-JJ1FHf8HdahTxfYkPS4k~ZMar7i1v9*m(lGeni|0UUP>oN4>hke&2F)NRJVY|f`{(3y)qkEez@>X7~|#;YHj<=%3{YoXT2Ap|3i;mJ)}%e zu7<~?W#BaG}&m|-|24_j(lCGW7O<>Tz;;^m2~3< zYP+s+W)IlIE(fS9Nq3Es|BN5LZl~0}pOYZrIN#LwT3?olRE?n$^MWO>u^uELxsf8r zeGx1yEcf*qk~YK!1|%pb2$!9npP%R8b8ZX5D0k1Ss(RuZ%|$X2C-=H%kEh(Qp`%e8 zpq|1dEg>lx+2Js7UPQDGSj!C;KmP$-yA0b*E~)QF+L}GkFJ_Oh{@U+j@ z&u>gotVk+32BBU${uhyu+{w-iGYkeRPD9bt&|LazXx#Ik&Y@cA zl8+im5tYW~7`$m%&k{|JkC#a2OZqA`4-1-|oux<~Hy=Ro*KBjQ``;rKHO1vx6@O_f50P0My2G(G_awt4$sp9_G(PNYGY3^|mVpE$hmNR*BYN zk#fy)PaK1A;LVk#?{@gt+FJ4oqejm#8K&HYRT4cH=(UL|p5VtTU&=CPSiGTjsp_r{ z$NdaLp7jlSKs1Gexl9NzXICc)!h{gpf|+P~u?rWJxu0L7VsUaR6=A}OFQuxg>Nk3N zdibHUv~(yba&67pIPI;eDWg*~6kPzFf>7{bB&IDv=VYsi{ic=9PUi zv|_-~JCv~wVVT73Hr%c!o>+KU1Q&S za7L_2VI^==V%zKLHF;N_0*vt?+qpR2f|tgnQeiK;#BcL47tK`Ls6_)1vl_YH?^7s|rO$#jLVRK>JJj2xu{iw*|4ivoq*+ zW>;&#N)_p%rS*$JLqo%ML;(*+(=+_?A(tUWpPaxf`H=`VuhX=~%KG{tTYP3_=5mYw zWx()fM`G6>p|5)?gof?NLskwRh`B|`m{$Yn64FO0sHzU>KeD@v$-F8kBI0Wb0>ETc zK5kE5Qc@yky+SAInSpKbhn0vb9)*|7@X4H%g z9xFS0_Nx*txQ&vGOxJ95G@*kSsu>eVT0KBgb6s8CEanQJ%JApU8*++mv9YiSf#3b) z^7He{dTgYj@%QeI_6z4l2_q}3RYg>JVxs0EXz%nINZ|hn^!#u=advLbXQ&f6{cPNe z3$%!lI5+p(Fm;X<&a?6H@#1X%ld0QuFpRO`=H`Y!8f^=P`Bzs}Q9KD>f(fX3v}V67 zz-M`rLn?OW5(A{CP>XA|`x_n>W_pUT@5VJ5yXpYC1ghUVpENtxV>T-tX zu9kHrK~hSU@6P`&QSum`{hpi4r2LWx0t*I0GyV3b^L~3)&a^#a3r)?<7Wf1N;_r59 zCzS()%r}3P@Br>F?da$T=&2t7#3z=?GcYt1YZLRTP(!fgXjF*-vum{0aSm1cc+cI| z7G3ss=GzEC)D2&7d1_rLJ~0yow}JaU;8{&NTH5Hp)BxY#16XvLZ}In&1HHou=!ByJ zuMT=H0AI2R5Yapv*d*fuJD*_^aBjtX0XQKRAgweLGjk6>2<58UTB|fR2M34Y;cW5S z{~Bt-@6tT$jZao!siNaIe-B#k-mm-n`|KZx=pGE-(}Wg}Hpa58tgQHt>;KuCY!t;# zY-HpgWPN#g`BHYkh23}2y(YJpTuE7+oSY?~zNbl<j!>^ioBGb0;;n=a?zkkEu>RIn@ zP_0P-Pf*Pi5#(fN|FBNAmE*MOP8jt{Tic_fr)T|oXcMH9q>s-z7cXyxqL^fLW#z$3 zuDk{Xh&jDvhB1 zuZ0xu*WYr!eVZs_;S5^gEiNu*zx+22;?^-XHqI+lN+~zB8UuxN&CJTWD*pxHmF8_| zIQt1aY}TFWp&`e`SUS;!FsX+~{Q8dfzCTkc75%ZZl)XXuCI9^S6Up1O-?8WB>iTVB zd|Z(nUsmjqPjOu?sNc75-)aLvGTEDN7M)sH2y_H@os2GEBhtai*vJKQA;6v$S>k~& zmgl?{jD)@S7sW>+9dQ3+WOGc4Xx%dh0ZNh%C)BTWUH#Do=30SI1qH8dy$7N|N9AB= z$Jy$8ym_ON{*2qj!^7WasUu8z-9SfYA}<(*doi;5Z&IixcC5wr4{S7yz0dMwqh4s0 zjyFk22np5oZg0PtHn4$_9nNcD8xXoasV%gHDPDZV8u|J&lc?%TCguUpWp30Zn14J2 zLa>%G@b-PR&G3T=qsQ16U@Q}8RBaveDP!*U@6Wq$W`u%pR=OKQMYzTWs?A;*7;p)( z3zD&%w358}P8RB2-S|%KU!*Z$ICxZfx@x&tr$3 zvxYtg>N7o*r_5foDhN4Y*)*f=GsJdXOcgW{6if|uia}@*3bei-4VH_)ucTyVH*G8$ z4a3-y^vtJ0H^c=Uu^shoQM#z{luHW9vXa?CsVi3Kiz(Z?-^b}5rQCEfC$~gBgKBo$ zg10l)wyVO=?pPZ0o5hT&5ShE|!y?xCJ>ZS^-ltoARkc}^=n#A-A?2!K^{zxRiKLJ+59#X60hNe|5azJ{F`vgfuOl{1(LLttNq8<&f%6t89aga3(BuB`%XtOO;JR zXQ7vHwh)rADkXgwUGER;Q9oaXw%|`&SB%TKrvg{eKU3CL1N4FetkI%J0-eLO*8@Mj z&^F=O&*^`V>>A^!$v@yTZBurbK3-lAyUA>KecCBv)uOu`dokjFw8n18po8wFQ+oW; zSMw-z@#?ZWFPpkdn(U*>+#RDHuiDVA8@)~L9eIZ3mUT?=MUv32-mgua1|-Fru#2Si ge?LbN-@9RW?OLDzX^j^T{D1~2%BsqgOPPlJ509$Xm;e9( diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_logo_icon.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/mapbox_logo_icon.png index 5f9647610a1458e227fe3b4f67bdbd6ff125cda4..e5780ccc071d00fc6e14ee6c94235106271b15ab 100644 GIT binary patch literal 14441 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 d%E6zos^Sknx4$2GeQ^iD->AHve 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 wd%6(RK> + android:width="21dp" + android:height="21dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0"> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_selected.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_selected.xml index 074928d05ad..ccbd1d8d399 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_selected.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/mapbox_info_icon_selected.xml @@ -1,9 +1,9 @@ + android:width="21dp" + android:height="21dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0"> + android:pathData="M11,17h2v-6h-2v6zm1,-15C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm0,18c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2V7h-2v2z"/> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml index e6a26777858..6d07de7baac 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml @@ -39,10 +39,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:adjustViewBounds="true" - android:background="@drawable/mapbox_default_bg_selector" android:clickable="true" + android:focusable="true" android:contentDescription="@string/mapbox_attributionsIconContentDescription" - android:padding="7dp" android:src="@drawable/mapbox_info_bg_selector"/> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml index d015bc57854..1c1ab0e71b6 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_preview.xml @@ -1,22 +1,29 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + android:contentDescription="@null" + android:src="@drawable/mapbox_mapview_preview" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:layout_alignParentStart="true"/> @@ -24,18 +31,22 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" - android:layout_marginBottom="@dimen/mapbox_seven_dp" - android:layout_marginLeft="@dimen/mapbox_seventy_six_dp" + android:layout_toEndOf="@+id/logoView" + android:contentDescription="@null" + android:layout_marginBottom="@dimen/mapbox_four_dp" android:background="@drawable/mapbox_default_bg_selector" - android:clickable="true" - android:contentDescription="@string/mapbox_attributionsIconContentDescription" - android:src="@drawable/mapbox_info_bg_selector" /> + android:src="@drawable/mapbox_info_bg_selector" + android:layout_marginLeft="@dimen/mapbox_four_dp" + android:layout_marginStart="@dimen/mapbox_four_dp" + android:layout_toRightOf="@+id/logoView"/> + android:contentDescription="@null" + android:src="@drawable/mapbox_compass_icon"/> diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml index df6983e11dd..ce20cb9a8bf 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml @@ -4,10 +4,15 @@ 8dp -2dp 1.5dp - 7dp + @dimen/mapbox_two_dp + @dimen/mapbox_two_dp + @dimen/mapbox_two_dp + @dimen/mapbox_two_dp + 2dp + 4dp 8dp 10dp 16dp - 76dp + 95dp 18dp diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java index 354f5def6f2..a1c46903bf3 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java @@ -15,6 +15,8 @@ import com.mapbox.mapboxsdk.style.layers.Property; import com.mapbox.mapboxsdk.style.layers.PropertyFactory; import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException; +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; +import com.mapbox.mapboxsdk.style.sources.RasterSource; import com.mapbox.mapboxsdk.style.sources.Source; import com.mapbox.mapboxsdk.style.sources.VectorSource; import com.mapbox.mapboxsdk.testapp.R; @@ -28,6 +30,8 @@ import org.junit.Test; import org.junit.runner.RunWith; +import java.net.MalformedURLException; +import java.net.URL; import java.util.List; import timber.log.Timber; @@ -190,6 +194,35 @@ public void testAddRemoveSource() { onView(withId(R.id.mapView)).perform(new AddRemoveSourceAction()); } + @Test + public void testVectorSourceUrlGetter() { + validateTestSetup(); + + VectorSource source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"); + mapboxMap.addSource(source); + assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUrl()); + } + + @Test + public void testRasterSourceUrlGetter() { + validateTestSetup(); + + RasterSource source = new RasterSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"); + mapboxMap.addSource(source); + assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUrl()); + } + + @Test + public void testGeoJsonSourceUrlGetter() throws MalformedURLException { + validateTestSetup(); + + GeoJsonSource source = new GeoJsonSource("my-source"); + mapboxMap.addSource(source); + assertNull(source.getUrl()); + source.setUrl(new URL("http://mapbox.com/my-file.json")); + assertEquals("http://mapbox.com/my-file.json", source.getUrl()); + } + /** * https://github.com/mapbox/mapbox-gl-native/issues/7973 */ diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java index 08399f3b3ee..60518239c86 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java @@ -43,10 +43,35 @@ protected void onCreate(Bundle savedInstanceState) { public void onMapReady(@NonNull final MapboxMap mapboxMap) { this.mapboxMap = mapboxMap; - mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() { + mapboxMap.setOnCameraIdleListener(new MapboxMap.OnCameraIdleListener() { @Override - public void onCameraChange(CameraPosition position) { - Timber.w("OnCameraChange: " + position); + public void onCameraIdle() { + Timber.e("OnCameraIdle"); + } + }); + + mapboxMap.setOnCameraMoveCancelListener(new MapboxMap.OnCameraMoveCanceledListener() { + @Override + public void onCameraMoveCanceled() { + Timber.e("OnCameraMoveCanceled"); + } + }); + + mapboxMap.setOnCameraMoveListener(new MapboxMap.OnCameraMoveListener() { + @Override + public void onCameraMove() { + Timber.e("OnCameraMove"); + } + }); + + mapboxMap.setOnCameraMoveStartedistener(new MapboxMap.OnCameraMoveStartedListener() { + + private final String[] REASONS = {"REASON_API_GESTURE", "REASON_DEVELOPER_ANIMATION", "REASON_API_ANIMATION"}; + + @Override + public void onCameraMoveStarted(int reason) { + // reason ranges from 1 <-> 3 + Timber.e("OnCameraMoveStarted: %s", REASONS[reason - 1]); } }); diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties index c7ad166b13b..1d35abd7b29 100644 --- a/platform/android/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip \ No newline at end of file diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp index 9b56446e31e..780cc4b6f6f 100644 --- a/platform/android/src/style/sources/geojson_source.cpp +++ b/platform/android/src/style/sources/geojson_source.cpp @@ -97,6 +97,11 @@ namespace android { source.as()->GeoJSONSource::setURL(jni::Make(env, url)); } + jni::String GeoJSONSource::getURL(jni::JNIEnv& env) { + optional url = source.as()->GeoJSONSource::getURL(); + return url ? jni::Make(env, *url) : jni::String(); + } + jni::Array> GeoJSONSource::querySourceFeatures(jni::JNIEnv& env, jni::Array> jfilter) { using namespace mbgl::android::conversion; @@ -133,6 +138,7 @@ namespace android { METHOD(&GeoJSONSource::setFeature, "nativeSetFeature"), METHOD(&GeoJSONSource::setGeometry, "nativeSetGeometry"), METHOD(&GeoJSONSource::setURL, "nativeSetUrl"), + METHOD(&GeoJSONSource::getURL, "nativeGetUrl"), METHOD(&GeoJSONSource::querySourceFeatures, "querySourceFeatures") ); } diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp index 51ea452fb2d..938a20612c6 100644 --- a/platform/android/src/style/sources/geojson_source.hpp +++ b/platform/android/src/style/sources/geojson_source.hpp @@ -38,6 +38,8 @@ class GeoJSONSource : public Source { jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array> jfilter); + jni::String getURL(jni::JNIEnv&); + jni::jobject* createJavaPeer(jni::JNIEnv&); }; // class GeoJSONSource diff --git a/platform/android/src/style/sources/raster_source.cpp b/platform/android/src/style/sources/raster_source.cpp index 0234901a77c..32fdb163b0c 100644 --- a/platform/android/src/style/sources/raster_source.cpp +++ b/platform/android/src/style/sources/raster_source.cpp @@ -28,6 +28,11 @@ namespace android { RasterSource::~RasterSource() = default; + jni::String RasterSource::getURL(jni::JNIEnv& env) { + optional url = source.as()->RasterSource::getURL(); + return url ? jni::Make(env, *url) : jni::String(); + } + jni::Class RasterSource::javaClass; jni::jobject* RasterSource::createJavaPeer(jni::JNIEnv& env) { @@ -46,7 +51,8 @@ namespace android { env, RasterSource::javaClass, "nativePtr", std::make_unique, jni::jint>, "initialize", - "finalize" + "finalize", + METHOD(&RasterSource::getURL, "nativeGetUrl") ); } diff --git a/platform/android/src/style/sources/raster_source.hpp b/platform/android/src/style/sources/raster_source.hpp index 6600096f6de..a79ccc10a4d 100644 --- a/platform/android/src/style/sources/raster_source.hpp +++ b/platform/android/src/style/sources/raster_source.hpp @@ -22,6 +22,8 @@ class RasterSource : public Source { ~RasterSource(); + jni::String getURL(jni::JNIEnv&); + jni::jobject* createJavaPeer(jni::JNIEnv&); }; // class RasterSource diff --git a/platform/android/src/style/sources/vector_source.cpp b/platform/android/src/style/sources/vector_source.cpp index a8f74df142e..e2d9f60dec4 100644 --- a/platform/android/src/style/sources/vector_source.cpp +++ b/platform/android/src/style/sources/vector_source.cpp @@ -34,6 +34,11 @@ namespace android { VectorSource::~VectorSource() = default; + jni::String VectorSource::getURL(jni::JNIEnv& env) { + optional url = source.as()->VectorSource::getURL(); + return url ? jni::Make(env, *url) : jni::String(); + } + jni::Array> VectorSource::querySourceFeatures(jni::JNIEnv& env, jni::Array jSourceLayerIds, jni::Array> jfilter) { @@ -66,7 +71,8 @@ namespace android { std::make_unique>, "initialize", "finalize", - METHOD(&VectorSource::querySourceFeatures, "querySourceFeatures") + METHOD(&VectorSource::querySourceFeatures, "querySourceFeatures"), + METHOD(&VectorSource::getURL, "nativeGetUrl") ); } diff --git a/platform/android/src/style/sources/vector_source.hpp b/platform/android/src/style/sources/vector_source.hpp index cac687bb6fc..643b4683386 100644 --- a/platform/android/src/style/sources/vector_source.hpp +++ b/platform/android/src/style/sources/vector_source.hpp @@ -26,6 +26,8 @@ class VectorSource : public Source { jni::Array> querySourceFeatures(jni::JNIEnv&, jni::Array, jni::Array> jfilter); + jni::String getURL(jni::JNIEnv&); + jni::jobject* createJavaPeer(jni::JNIEnv&); }; // class VectorSource diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp index 27c3950e2a4..7db0b854611 100644 --- a/platform/default/default_file_source.cpp +++ b/platform/default/default_file_source.cpp @@ -200,12 +200,16 @@ std::string DefaultFileSource::getAccessToken() const { } void DefaultFileSource::setResourceTransform(std::function transform) { - auto loop = util::RunLoop::Get(); - thread->invoke(&Impl::setResourceTransform, [loop, transform](Resource::Kind kind_, std::string&& url_, auto callback_) { - return loop->invokeWithCallback([transform](Resource::Kind kind, std::string&& url, auto callback) { - callback(transform(kind, std::move(url))); - }, kind_, std::move(url_), callback_); - }); + if (transform) { + auto loop = util::RunLoop::Get(); + thread->invoke(&Impl::setResourceTransform, [loop, transform](Resource::Kind kind_, std::string&& url_, auto callback_) { + return loop->invokeWithCallback([transform](Resource::Kind kind, std::string&& url, auto callback) { + callback(transform(kind, std::move(url))); + }, kind_, std::move(url_), callback_); + }); + } else { + thread->invoke(&Impl::setResourceTransform, nullptr); + } } std::unique_ptr DefaultFileSource::request(const Resource& resource, Callback callback) {