From 8ed1dc9f7412d61a66bae576346f2674e6ab3926 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Mon, 11 Jan 2016 11:32:00 +0100 Subject: [PATCH] [android] #3145 - MapboxMap --- .../android/MapboxGLAndroidSDK/build.gradle | 1 - .../mapboxsdk/annotations/Annotation.java | 20 +- .../mapbox/mapboxsdk/annotations/Icon.java | 4 +- .../mapboxsdk/annotations/InfoWindow.java | 44 +- .../mapbox/mapboxsdk/annotations/Marker.java | 45 +- .../mapboxsdk/camera/CameraPosition.java | 122 +- .../mapbox/mapboxsdk/camera/CameraUpdate.java | 53 +- .../mapboxsdk/camera/CameraUpdateFactory.java | 214 +- .../mapboxsdk/constants/MapboxConstants.java | 69 + .../constants/MyBearingTracking.java | 5 +- .../constants/MyLocationTracking.java | 7 +- .../com/mapbox/mapboxsdk/constants/Style.java | 2 +- .../IconBitmapChangedException.java | 2 +- .../InvalidAccessTokenException.java | 2 +- .../mapboxsdk/geometry/LatLngBounds.java | 296 ++ .../mapbox/mapboxsdk/geometry/LatLngZoom.java | 96 - .../{views => maps}/CompassView.java | 4 +- .../mapboxsdk/{ => maps}/MapFragment.java | 113 +- .../mapboxsdk/{views => maps}/MapView.java | 2706 +++++------------ .../com/mapbox/mapboxsdk/maps/MapboxMap.java | 1557 ++++++++++ .../mapboxsdk/maps/MapboxMapOptions.java | 114 + .../{views => maps}/NativeMapView.java | 57 +- .../mapboxsdk/maps/OnMapReadyCallback.java | 26 + .../{views => maps}/UserLocationView.java | 15 +- .../mapbox/mapboxsdk/maps/package-info.java | 4 + .../com/mapbox/mapboxsdk/package-info.java | 3 +- .../com/mapbox/mapboxsdk/utils/ApiAccess.java | 1 - .../mapbox/mapboxsdk/views/package-info.java | 5 - .../src/main/res/layout/fragment_mapview.xml | 2 +- .../src/main/res/layout/mapview_internal.xml | 4 +- .../src/main/res/values/attrs.xml | 2 +- .../src/main/res/values/dimens.xml | 4 + .../MapboxGLAndroidSDKTestApp/build.gradle | 4 + .../src/main/AndroidManifest.xml | 5 + .../mapboxsdk/testapp/BulkMarkerActivity.java | 79 +- .../mapboxsdk/testapp/CameraActivity.java | 152 +- .../testapp/CoordinateChangeActivity.java | 25 +- .../mapboxsdk/testapp/DirectionsActivity.java | 31 +- .../mapboxsdk/testapp/DoubleMapActivity.java | 52 +- .../mapboxsdk/testapp/GeocoderActivity.java | 51 +- .../mapboxsdk/testapp/InfoWindowActivity.java | 73 +- .../testapp/InfoWindowAdapterActivity.java | 50 +- .../testapp/InfoWindowConcurrentActivity.java | 35 +- .../mapboxsdk/testapp/MainActivity.java | 274 +- .../mapboxsdk/testapp/ManualZoomActivity.java | 69 +- .../testapp/MapFragmentActivity.java | 48 +- .../mapboxsdk/testapp/MapboxMapActivity.java | 114 + .../mapboxsdk/testapp/MaxMinZoomActivity.java | 134 + .../MyLocationTrackingModeActivity.java | 83 +- .../mapboxsdk/testapp/PolylineActivity.java | 34 +- .../testapp/PressForMarkerActivity.java | 100 +- .../mapboxsdk/testapp/TiltActivity.java | 46 +- .../VisibleCoordinateBoundsActivity.java | 57 +- .../res/drawable/ic_find_replace_24dp.xml | 9 + .../src/main/res/drawable/ic_mapboxmap.xml | 9 + .../layout/activity_animate_coordinate.xml | 2 +- .../src/main/res/layout/activity_camera.xml | 2 +- .../main/res/layout/activity_directions.xml | 2 +- .../src/main/res/layout/activity_geocoder.xml | 2 +- .../main/res/layout/activity_infowindow.xml | 2 +- .../layout/activity_infowindow_adapter.xml | 2 +- .../layout/activity_infowindow_concurrent.xml | 2 +- .../src/main/res/layout/activity_main.xml | 2 +- .../main/res/layout/activity_manual_zoom.xml | 22 +- .../main/res/layout/activity_mapboxmap.xml | 24 + .../main/res/layout/activity_marker_bulk.xml | 2 +- .../main/res/layout/activity_maxmin_zoom.xml | 20 + .../layout/activity_my_location_tracking.xml | 2 +- .../src/main/res/layout/activity_polyline.xml | 2 +- .../src/main/res/layout/activity_tilt.xml | 2 +- .../res/layout/activity_visible_bounds.xml | 2 +- .../main/res/layout/fragment_double_map.xml | 4 +- .../src/main/res/menu/menu_drawer.xml | 12 + .../src/main/res/menu/menu_zoom.xml | 25 + .../src/main/res/values/strings.xml | 3 + .../src/test/java/LatLngZoomTest.java | 15 - .../mapboxsdk/maps}/BoundingBoxTest.java | 2 + .../mapboxsdk/maps}/CoordinateBoundsTest.java | 2 + .../mapboxsdk/maps}/CoordinateRegionTest.java | 2 + .../mapboxsdk/maps}/CoordinateSpanTest.java | 2 + .../mapbox/mapboxsdk/maps}/LatLngTest.java | 2 + .../mapbox/mapboxsdk/maps/MapboxMapTest.java | 235 ++ .../mapbox/mapboxsdk/maps}/MarkerTest.java | 2 + .../mapbox/mapboxsdk/maps}/PolygonTest.java | 2 + .../mapbox/mapboxsdk/maps}/PolylineTest.java | 2 + .../mapboxsdk/maps}/ProjectedMetersTest.java | 2 + platform/android/src/jni.cpp | 87 +- 87 files changed, 4587 insertions(+), 3037 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngZoom.java rename platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/{views => maps}/CompassView.java (98%) rename platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/{ => maps}/MapFragment.java (60%) rename platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/{views => maps}/MapView.java (56%) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java rename platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/{views => maps}/NativeMapView.java (93%) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java rename platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/{views => maps}/UserLocationView.java (97%) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/package-info.java delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/package-info.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_find_replace_24dp.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_mapboxmap.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_mapboxmap.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_zoom.xml delete mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/test/java/LatLngZoomTest.java rename platform/android/MapboxGLAndroidSDKTestApp/src/test/java/{ => com/mapbox/mapboxsdk/maps}/BoundingBoxTest.java (99%) rename platform/android/MapboxGLAndroidSDKTestApp/src/test/java/{ => com/mapbox/mapboxsdk/maps}/CoordinateBoundsTest.java (98%) rename platform/android/MapboxGLAndroidSDKTestApp/src/test/java/{ => com/mapbox/mapboxsdk/maps}/CoordinateRegionTest.java (98%) rename platform/android/MapboxGLAndroidSDKTestApp/src/test/java/{ => com/mapbox/mapboxsdk/maps}/CoordinateSpanTest.java (97%) rename platform/android/MapboxGLAndroidSDKTestApp/src/test/java/{ => com/mapbox/mapboxsdk/maps}/LatLngTest.java (98%) create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java rename platform/android/MapboxGLAndroidSDKTestApp/src/test/java/{ => com/mapbox/mapboxsdk/maps}/MarkerTest.java (98%) rename platform/android/MapboxGLAndroidSDKTestApp/src/test/java/{ => com/mapbox/mapboxsdk/maps}/PolygonTest.java (98%) rename platform/android/MapboxGLAndroidSDKTestApp/src/test/java/{ => com/mapbox/mapboxsdk/maps}/PolylineTest.java (98%) rename platform/android/MapboxGLAndroidSDKTestApp/src/test/java/{ => com/mapbox/mapboxsdk/maps}/ProjectedMetersTest.java (90%) diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle index c194a8c34..8b44873a2 100644 --- a/platform/android/MapboxGLAndroidSDK/build.gradle +++ b/platform/android/MapboxGLAndroidSDK/build.gradle @@ -54,7 +54,6 @@ android { lintOptions { checkAllWarnings true warningsAsErrors true - disable 'InvalidPackage' } buildTypes { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java index 813e489e9..ce6a3ee55 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java @@ -2,7 +2,8 @@ package com.mapbox.mapboxsdk.annotations; import android.support.annotation.NonNull; -import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; /** * Annotation is a overlay on top of a {@link MapView}, @@ -21,7 +22,7 @@ public abstract class Annotation implements Comparable { * Internal C++ id is stored as unsigned int. */ private long id = -1; // -1 unless added to a MapView - private MapView mapView; + private MapboxMap mapboxMap; protected Annotation() { } @@ -38,10 +39,10 @@ public abstract class Annotation implements Comparable { } public void remove() { - if (mapView == null) { + if (mapboxMap == null) { return; } - mapView.removeAnnotation(this); + mapboxMap.removeAnnotation(this); } /** @@ -54,15 +55,12 @@ public abstract class Annotation implements Comparable { /** * Do not use this method. Used internally by the SDK. */ - public void setMapView(MapView mapView) { - this.mapView = mapView; + public void setMapboxMap(MapboxMap mapView) { + this.mapboxMap = mapView; } - protected MapView getMapView() { - if (mapView == null) { - return null; - } - return mapView; + protected MapboxMap getMapboxMap() { + return mapboxMap; } @Override diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java index b9691914e..e30b81d4c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java @@ -2,8 +2,10 @@ package com.mapbox.mapboxsdk.annotations; import android.graphics.Bitmap; +import com.mapbox.mapboxsdk.maps.MapView; + /** - * Icon is the visual representation of a {@link Marker} on a {@link com.mapbox.mapboxsdk.views.MapView}. + * Icon is the visual representation of a {@link Marker} on a {@link MapView}. * @see Marker */ public final class Icon { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java index 696301cf5..e936b7bd2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java @@ -9,9 +9,10 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.geometry.LatLng; -import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.maps.MapView; import java.lang.ref.WeakReference; @@ -26,7 +27,7 @@ import java.lang.ref.WeakReference; public class InfoWindow { private WeakReference mBoundMarker; - private WeakReference mMapView; + private WeakReference mMapboxMap; protected WeakReference mView; private float mMarkerHeightOffset; @@ -37,18 +38,18 @@ public class InfoWindow { @LayoutRes private int mLayoutRes; - InfoWindow(int layoutResId, MapView mapView) { + InfoWindow(MapView mapView, int layoutResId, MapboxMap mapboxMap) { mLayoutRes = layoutResId; View view = LayoutInflater.from(mapView.getContext()).inflate(layoutResId, mapView, false); - initialize(view, mapView); + initialize(view, mapboxMap); } - InfoWindow(View view, MapView mapView) { - initialize(view, mapView); + InfoWindow(View view, MapboxMap mapboxMap) { + initialize(view, mapboxMap); } - private void initialize(View view, MapView mapView) { - mMapView = new WeakReference<>(mapView); + private void initialize(View view, MapboxMap mapboxMap) { + mMapboxMap = new WeakReference<>(mapboxMap); mIsVisible = false; mView = new WeakReference<>(view); @@ -58,8 +59,8 @@ public class InfoWindow { public boolean onTouch(View v, MotionEvent e) { if (e.getAction() == MotionEvent.ACTION_UP) { boolean handledDefaultClick = false; - MapView.OnInfoWindowClickListener onInfoWindowClickListener = - mMapView.get().getOnInfoWindowClickListener(); + MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener = + mMapboxMap.get().getOnInfoWindowClickListener(); if (onInfoWindowClickListener != null) { handledDefaultClick = onInfoWindowClickListener.onMarkerClick(getBoundMarker()); } @@ -88,15 +89,17 @@ public class InfoWindow { MapView.LayoutParams lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, MapView.LayoutParams.WRAP_CONTENT); + MapboxMap mapboxMap = mMapboxMap.get(); View view = mView.get(); - if (view != null) { + if (view != null && mapboxMap != null) { view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); // Calculate y-offset for update method mMarkerHeightOffset = -view.getMeasuredHeight() + offsetY; // Calculate default Android x,y coordinate - mCoordinates = mapView.toScreenLocation(position); + + mCoordinates = mapboxMap.toScreenLocation(position); float x = mCoordinates.x - (view.getMeasuredWidth() / 2) + offsetX; float y = mCoordinates.y - view.getMeasuredHeight() + offsetY; @@ -191,13 +194,13 @@ public class InfoWindow { * * @param overlayItem the tapped overlay item */ - void adaptDefaultMarker(Marker overlayItem, MapView mapView) { + void adaptDefaultMarker(Marker overlayItem, MapboxMap mapboxMap, MapView mapView) { View view = mView.get(); if (view == null) { view = LayoutInflater.from(mapView.getContext()).inflate(mLayoutRes, mapView, false); - initialize(view, mapView); + initialize(view, mapboxMap); } - mMapView = new WeakReference<>(mapView); + mMapboxMap = new WeakReference<>(mapboxMap); String title = overlayItem.getTitle(); ((TextView) view.findViewById(R.id.infowindow_title)).setText(title); String snippet = overlayItem.getSnippet(); @@ -205,7 +208,10 @@ public class InfoWindow { } private void onClose() { - mMapView.get().deselectMarker(getBoundMarker()); + MapboxMap mapboxMap = mMapboxMap.get(); + if (mapboxMap != null) { + mapboxMap.deselectMarker(getBoundMarker()); + } } InfoWindow setBoundMarker(Marker boundMarker) { @@ -221,11 +227,11 @@ public class InfoWindow { } public void update() { - MapView mapView = mMapView.get(); + MapboxMap mapboxMap = mMapboxMap.get(); Marker marker = mBoundMarker.get(); View view = mView.get(); - if (mapView != null && marker != null && view != null) { - mCoordinates = mapView.toScreenLocation(marker.getPosition()); + if (mapboxMap != null && marker != null && view != null) { + mCoordinates = mapboxMap.toScreenLocation(marker.getPosition()); view.setX(mCoordinates.x + mViewWidthOffset); view.setY(mCoordinates.y + mMarkerHeightOffset); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java index 346380144..27c9c0369 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java @@ -4,15 +4,16 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.View; +import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.geometry.LatLng; -import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.maps.MapView; /** * Marker is an annotation that shows an icon image at a geographical location. *

* An {@link InfoWindow} can be shown when a Marker is pressed - *

+ *

*/ public final class Marker extends Annotation { @@ -55,8 +56,6 @@ public final class Marker extends Annotation { /** * Do not use this method. Used internally by the SDK. - * - * @return boolean State of a InfoWindow */ public boolean isInfoWindowShown() { return infoWindowShown; @@ -72,8 +71,6 @@ public final class Marker extends Annotation { /** * Do not use this method. Used internally by the SDK. - * - * @param icon The icon to be used as Marker image */ public void setIcon(@Nullable Icon icon) { this.icon = icon; @@ -89,25 +86,25 @@ public final class Marker extends Annotation { /** * Do not use this method. Used internally by the SDK. - * - * @param mapView The MapView to show the InfoWindow on. - * @return infoWindow The infoWindow to show */ - public InfoWindow showInfoWindow(@NonNull MapView mapView) { - setMapView(mapView); - MapView.InfoWindowAdapter infoWindowAdapter = getMapView().getInfoWindowAdapter(); + public InfoWindow showInfoWindow(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) { + setMapboxMap(mapboxMap); + MapboxMap.InfoWindowAdapter infoWindowAdapter = getMapboxMap().getInfoWindowAdapter(); if (infoWindowAdapter != null) { // end developer is using a custom InfoWindowAdapter View content = infoWindowAdapter.getInfoWindow(this); if (content != null) { - infoWindow = new InfoWindow(content, getMapView()); + infoWindow = new InfoWindow(content, mapboxMap); showInfoWindow(infoWindow, mapView); return infoWindow; } } - getInfoWindow().adaptDefaultMarker(this, mapView); - return showInfoWindow(getInfoWindow(), mapView); + InfoWindow infoWindow = getInfoWindow(mapView); + if (mapView.getContext() != null) { + infoWindow.adaptDefaultMarker(this, mapboxMap, mapView); + } + return showInfoWindow(infoWindow, mapView); } private InfoWindow showInfoWindow(InfoWindow iw, MapView mapView) { @@ -116,27 +113,15 @@ public final class Marker extends Annotation { return iw; } - private InfoWindow getInfoWindow() { - if (infoWindow == null) { - infoWindow = new InfoWindow(R.layout.infowindow_view, getMapView()); + private InfoWindow getInfoWindow(@NonNull MapView mapView) { + if (infoWindow == null && mapView.getContext() != null) { + infoWindow = new InfoWindow(mapView, R.layout.infowindow_view, getMapboxMap()); } return infoWindow; } - /* - @Override - void setVisible(boolean visible) { - super.setVisible(visible); - if (!visible && infoWindowShown) { - hideInfoWindow(); - } - } - */ - /** * Do not use this method. Used internally by the SDK. - * - * @param topOffsetPixels the pixels to have as offset */ public void setTopOffsetPixels(int topOffsetPixels) { this.topOffsetPixels = topOffsetPixels; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java index 7b98a0df3..6b059ed47 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java @@ -1,9 +1,17 @@ package com.mapbox.mapboxsdk.camera; +import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.FloatRange; + +import com.mapbox.mapboxsdk.R; +import com.mapbox.mapboxsdk.constants.MapboxConstants; +import com.mapbox.mapboxsdk.constants.MathConstants; import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.utils.MathUtils; public final class CameraPosition implements Parcelable { @@ -44,35 +52,22 @@ public final class CameraPosition implements Parcelable { public final float zoom; /** - * * Constructs a CameraPosition. - * @param target The target location to align with the center of the screen. - * @param zoom Zoom level at target. See zoom(float) for details of restrictions. - * @param tilt The camera angle, in degrees, from the nadir (directly down). See tilt(float) for details of restrictions. + * + * @param target The target location to align with the center of the screen. + * @param zoom Zoom level at target. See zoom(float) for details of restrictions. + * @param tilt The camera angle, in degrees, from the nadir (directly down). See tilt(float) for details of restrictions. * @param bearing Direction that the camera is pointing in, in degrees clockwise from north. This value will be normalized to be within 0 degrees inclusive and 360 degrees exclusive. - * @throws NullPointerException if target is null + * @throws NullPointerException if target is null * @throws IllegalArgumentException if tilt is outside the range of 0 to 90 degrees inclusive. */ - public CameraPosition (LatLng target, float zoom, float tilt, float bearing) throws NullPointerException, IllegalArgumentException{ - super(); - if (target == null) { - throw new NullPointerException("target is NULL"); - } + CameraPosition(LatLng target, float zoom, float tilt, float bearing) { this.target = target; - - // Allow for default value of -1 - if (tilt != -1) { - if (tilt < 0.0f || tilt > 90.0f) { - throw new IllegalArgumentException("tilt is outside of 0 to 90 degrees range"); - } - } - this.tilt = tilt; - this.bearing = bearing; + this.tilt = tilt; this.zoom = zoom; } - @Override public int describeContents() { return 0; @@ -86,6 +81,36 @@ public final class CameraPosition implements Parcelable { out.writeFloat(zoom); } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + CameraPosition cameraPosition = (CameraPosition) o; + if (!target.equals(cameraPosition.target)) { + return false; + } else if (zoom != cameraPosition.zoom) { + return false; + } else if (tilt != cameraPosition.tilt) { + return false; + } else if (bearing != cameraPosition.bearing) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + (target != null ? target.hashCode() : 0); + return result; + } + /** * Builds camera position. */ @@ -105,6 +130,7 @@ public final class CameraPosition implements Parcelable { /** * Create Builder with an existing CameraPosition data. + * * @param previous Existing CameraPosition values to use */ public Builder(CameraPosition previous) { @@ -117,18 +143,65 @@ public final class CameraPosition implements Parcelable { } } + /** + * Create Builder with an existing CameraPosition data. + * + * @param typedArray TypedArray containgin attribute values + */ + public Builder(TypedArray typedArray){ + super(); + if(typedArray!=null) { + this.bearing = typedArray.getFloat(R.styleable.MapView_direction, 0.0f); + double lat = typedArray.getFloat(R.styleable.MapView_center_latitude, 0.0f); + double lng = typedArray.getFloat(R.styleable.MapView_center_longitude, 0.0f); + this.target= new LatLng(lat, lng); + this.tilt = typedArray.getFloat(R.styleable.MapView_tilt, 0.0f); + this.zoom = typedArray.getFloat(R.styleable.MapView_zoom, 0.0f); + } + } + + /** + * Create Builder from an existing PositionCameraUpdate update. + * + * @param update Update containing camera options + */ + public Builder(CameraUpdateFactory.PositionCameraUpdate update) { + super(); + if (update != null) { + this.bearing = update.getBearing(); + this.target = update.getTarget(); + this.tilt = update.getTilt(); + this.zoom = update.getZoom(); + } + } + + + /** + * Create Builder from an existing PositionCameraUpdate update. + * + * @param update Update containing camera options + */ + public Builder(CameraUpdateFactory.ZoomUpdate update){ + super(); + if(update!=null){ + this.zoom = update.getZoom(); + } + } + /** * Sets the direction that the camera is pointing in, in degrees clockwise from north. + * * @param bearing Bearing * @return Builder */ - public Builder bearing (float bearing) { - this.bearing = bearing; + public Builder bearing(float bearing) { + this.bearing = (float) (-bearing * MathConstants.DEG2RAD); return this; } /** * Builds a CameraPosition. + * * @return CameraPosition */ public CameraPosition build() { @@ -137,6 +210,7 @@ public final class CameraPosition implements Parcelable { /** * Sets the location that the camera is pointing at. + * * @param location Location * @return Builder */ @@ -147,17 +221,19 @@ public final class CameraPosition implements Parcelable { /** * Set the tilt + * * @param tilt Tilt value * @return Builder */ @FloatRange(from = 0.0, to = 60.0) public Builder tilt(float tilt) { - this.tilt = tilt; + this.tilt = (float) (MathUtils.clamp(tilt, MapboxConstants.MINIMUM_TILT, MapboxConstants.MAXIMUM_TILT) * MathConstants.DEG2RAD); return this; } /** * Set the zoom + * * @param zoom Zoom value * @return Builder */ diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java index 33f551550..61f3a2ecf 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java @@ -1,56 +1,5 @@ package com.mapbox.mapboxsdk.camera; -import com.mapbox.mapboxsdk.geometry.LatLng; +public interface CameraUpdate { -public final class CameraUpdate { - - /** - * Direction that the camera is pointing in, in degrees clockwise from north. - */ - private final float bearing; - - /** - * The location that the camera is pointing at. - */ - private final LatLng target; - - /** - * The angle, in degrees, of the camera angle from the nadir (directly facing the Earth). See tilt(float) for details of restrictions on the range of values. - */ - private final float tilt; - - /** - * Zoom level near the center of the screen. See zoom(float) for the definition of the camera's zoom level. - */ - private final float zoom; - - /** - * Package Private Constructor to only be used CameraUpdateFactory - * @param bearing Final Bearing - * @param target Final Target - * @param tilt Final Tilt - * @param zoom Final Zoom - */ - CameraUpdate(float bearing, LatLng target, float tilt, float zoom) { - this.bearing = bearing; - this.target = target; - this.tilt = tilt; - this.zoom = zoom; - } - - public float getBearing() { - return bearing; - } - - public LatLng getTarget() { - return target; - } - - public float getTilt() { - return tilt; - } - - public float getZoom() { - return zoom; - } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java index 3ba2090bd..6f39f8b7c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java @@ -1,15 +1,225 @@ package com.mapbox.mapboxsdk.camera; +import android.graphics.Point; +import android.support.annotation.IntDef; import android.support.annotation.NonNull; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.geometry.LatLngBounds; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + public class CameraUpdateFactory { /** * Returns a CameraUpdate that moves the camera to a specified CameraPosition. + * * @param cameraPosition Camera Position to change to * @return CameraUpdate Final Camera Position data */ - public static CameraUpdate newCameraPosition (@NonNull CameraPosition cameraPosition) { - return new CameraUpdate(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom); + public static CameraUpdate newCameraPosition(@NonNull CameraPosition cameraPosition) { + return new PositionCameraUpdate(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom); + } + + /** + * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude + * specified by a LatLng object. This centers the camera on the LatLng object. + * + * @param latLng + * @return + */ + public static CameraUpdate newLatLng(@NonNull LatLng latLng) { + return new PositionCameraUpdate(-1, latLng, -1, -1); + } + + /** + * Returns a CameraUpdate that transforms the camera such that the specified latitude/longitude + * bounds are centered on screen at the greatest possible zoom level. + * You can specify padding, in order to inset the bounding box from the map view's edges. + * The returned CameraUpdate has a bearing of 0 and a tilt of 0. + * + * @param bounds + * @param padding + * @return + */ + public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int padding) { + throw new UnsupportedOperationException("Not implemented yet"); + } + + /** + * Returns a CameraUpdate that transforms the camera such that the specified latitude/longitude + * bounds are centered on screen within a bounding box of specified dimensions at the greatest + * possible zoom level. You can specify additional padding, to further restrict the size of + * the bounding box. The returned CameraUpdate has a bearing of 0 and a tilt of 0. + * + * @param bounds + * @param width + * @param height + * @param padding + * @return + */ + public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int width, int height, int padding) { + throw new UnsupportedOperationException("Not implemented yet"); + } + + /** + * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude specified by a LatLng object, and moves to the given zoom level. + * + * @param latLng + * @param zoom + * @return + */ + public static CameraUpdate newLatLngZoom(@NonNull LatLng latLng, float zoom) { + return new PositionCameraUpdate(-1, latLng, -1, zoom); + } + + /** + * Returns a CameraUpdate that scrolls the camera over the map, shifting the center of view by the specified number of pixels in the x and y directions. + * + * @param xPixel + * @param yPixel + * @return + */ + public static CameraUpdate scrollBy(float xPixel, float yPixel) { + throw new UnsupportedOperationException("Not implemented yet"); + } + + /** + * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint. + * + * @param amount + * @param focus + * @return + */ + public static CameraUpdate zoomBy(float amount, Point focus) { + return new ZoomUpdate(ZoomUpdate.ZOOM_TO_POINT, focus.x, focus.y); + } + + /** + * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint. + * + * @param amount + * @return + */ + public static CameraUpdate zoomBy(float amount) { + return new ZoomUpdate(ZoomUpdate.ZOOM_BY, amount); + } + + /** + * Returns a CameraUpdate that zooms in on the map by moving the viewpoint's height closer to the Earth's surface. The zoom increment is 1.0. + * + * @return + */ + public static CameraUpdate zoomIn() { + return new ZoomUpdate(ZoomUpdate.ZOOM_IN); + } + + /** + * Returns a CameraUpdate that zooms out on the map by moving the viewpoint's height farther away from the Earth's surface. The zoom increment is -1.0. + * + * @return + */ + public static CameraUpdate zoomOut() { + return new ZoomUpdate(ZoomUpdate.ZOOM_OUT); + } + + /** + * Returns a CameraUpdate that moves the camera viewpoint to a particular zoom level. + * + * @param zoom + * @return + */ + public static CameraUpdate zoomTo(float zoom) { + return new ZoomUpdate(ZoomUpdate.ZOOM_TO, zoom); + } + + // + // CameraUpdate types + // + + public static class PositionCameraUpdate implements CameraUpdate { + + private final float bearing; + private final LatLng target; + private final float tilt; + private final float zoom; + + PositionCameraUpdate(float bearing, LatLng target, float tilt, float zoom) { + this.bearing = bearing; + this.target = target; + this.tilt = tilt; + this.zoom = zoom; + } + + public LatLng getTarget() { + return target; + } + + public float getBearing() { + return bearing; + } + + public float getTilt() { + return tilt; + } + + public float getZoom() { + return zoom; + } + } + + public static class ZoomUpdate implements CameraUpdate { + + @IntDef({ZOOM_IN, ZOOM_OUT, ZOOM_BY, ZOOM_TO, ZOOM_TO_POINT}) + @Retention(RetentionPolicy.SOURCE) + public @interface Type { + } + + public static final int ZOOM_IN = 0; + public static final int ZOOM_OUT = 1; + public static final int ZOOM_BY = 2; + public static final int ZOOM_TO = 3; + public static final int ZOOM_TO_POINT = 4; + + @Type + private final int type; + private final float zoom; + private float x; + private float y; + + ZoomUpdate(@Type int type) { + this.type = type; + this.zoom = 0; + } + + ZoomUpdate(@Type int type, float zoom) { + this.type = type; + this.zoom = zoom; + } + + ZoomUpdate(float zoom, float x, float y) { + this.type = ZOOM_TO_POINT; + this.zoom = zoom; + this.x = x; + this.y = y; + } + + public float getZoom() { + return zoom; + } + + @Type + public int getType() { + return type; + } + + public float getX() { + return x; + } + + public float getY() { + return y; + } } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java index 33b3d46a6..ed831c6bb 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java @@ -17,4 +17,73 @@ public class MapboxConstants { */ public static final String KEY_META_DATA_MANIFEST = "com.mapbox.AccessToken"; + /** + * Default animation time + */ + public static final int ANIMATION_DURATION = 300; + + /** + * The currently supported minimum zoom level. + */ + public static final double MINIMUM_ZOOM = 0f; + + /** + * The currently supported maximum zoom level. + */ + public static final double MAXIMUM_ZOOM = 25.0; + + /** + * The currently supported maximum tilt value. + */ + public static final double MAXIMUM_TILT = 60; + + /** + * The currently supported minimum tilt value. + */ + public static final double MINIMUM_TILT = 0; + + /** + * The currently supported maximum direction + */ + public static final double MAXIMUM_DIRECTION = 360; + + /** + * The currently supported minimum direction + */ + public static final double MINIMUM_DIRECTION = 0; + + // Save instance state keys + public static final String STATE_CAMERA_POSITION = "cameraPosition"; + public static final String STATE_ZOOM_ENABLED = "zoomEnabled"; + public static final String STATE_SCROLL_ENABLED = "scrollEnabled"; + public static final String STATE_ROTATE_ENABLED = "rotateEnabled"; + public static final String STATE_TILT_ENABLED = "tiltEnabled"; + public static final String STATE_ZOOM_CONTROLS_ENABLED = "zoomControlsEnabled"; + public static final String STATE_DEBUG_ACTIVE = "debugActive"; + public static final String STATE_STYLE_URL = "styleUrl"; + public static final String STATE_ACCESS_TOKEN = "accessToken"; + public static final String STATE_DEFAULT_TRANSITION_DURATION = "defaultTransitionDuration"; + public static final String STATE_MY_LOCATION_ENABLED = "myLocationEnabled"; + public static final String STATE_MY_LOCATION_TRACKING_MODE = "myLocationTracking"; + public static final String STATE_MY_BEARING_TRACKING_MODE = "myBearingTracking"; + public static final String STATE_COMPASS_ENABLED = "compassEnabled"; + public static final String STATE_COMPASS_GRAVITY = "compassGravity"; + public static final String STATE_COMPASS_MARGIN_LEFT = "compassMarginLeft"; + public static final String STATE_COMPASS_MARGIN_TOP = "compassMarginTop"; + public static final String STATE_COMPASS_MARGIN_RIGHT = "compassMarginRight"; + public static final String STATE_COMPASS_MARGIN_BOTTOM = "compassMarginBottom"; + public static final String STATE_LOGO_GRAVITY = "logoGravity"; + public static final String STATE_LOGO_MARGIN_LEFT = "logoMarginLeft"; + public static final String STATE_LOGO_MARGIN_TOP = "logoMarginTop"; + public static final String STATE_LOGO_MARGIN_RIGHT = "logoMarginRight"; + public static final String STATE_LOGO_MARGIN_BOTTOM = "logoMarginBottom"; + public static final String STATE_LOGO_VISIBILITY = "logoVisibility"; + public static final String STATE_ATTRIBUTION_GRAVITY = "attrGravity"; + public static final String STATE_ATTRIBUTION_MARGIN_LEFT = "attrMarginLeft"; + public static final String STATE_ATTRIBUTION_MARGIN_TOP = "attrMarginTop"; + public static final String STATE_ATTRIBUTION_MARGIN_RIGHT = "attrMarginRight"; + public static final String STATE_ATTRIBUTION_MARGIN_BOTTOM = "atrrMarginBottom"; + public static final String STATE_ATTRIBUTION_VISIBILITY = "atrrVisibility"; + + public static final String TAG = "MapboxMap"; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java index a70d37ded..2374a98fc 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java @@ -2,7 +2,8 @@ package com.mapbox.mapboxsdk.constants; import android.support.annotation.IntDef; -import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.UserLocationView; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -11,7 +12,7 @@ import java.lang.annotation.RetentionPolicy; * MyBearingTracking exposes different types bearing tracking modes. * * @see MapView#setMyBearingTrackingMode(int) - * @see com.mapbox.mapboxsdk.views.UserLocationView#setMyBearingTrackingMode(int) + * @see UserLocationView#setMyBearingTrackingMode(int) */ public class MyBearingTracking { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java index 130ca36f7..a8008d374 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java @@ -2,7 +2,8 @@ package com.mapbox.mapboxsdk.constants; import android.support.annotation.IntDef; -import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.UserLocationView; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -11,7 +12,7 @@ import java.lang.annotation.RetentionPolicy; * MyLocationTracking exposes different types of locational tracking modes. * * @see MapView#setMyLocationTrackingMode(int) - * @see com.mapbox.mapboxsdk.views.UserLocationView#setMyLocationTrackingMode(int) + * @see UserLocationView#setMyLocationTrackingMode(int) */ public class MyLocationTracking { @@ -29,7 +30,7 @@ public class MyLocationTracking { public static final int TRACKING_NONE = 0x00000000; /** - * Tracking the location of the user, {@link MapView} will reposition to center of {@link com.mapbox.mapboxsdk.views.UserLocationView} + * Tracking the location of the user, {@link MapView} will reposition to center of {@link UserLocationView} */ public static final int TRACKING_FOLLOW = 0x00000004; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java index 11ee9c315..31c146b43 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java @@ -2,7 +2,7 @@ package com.mapbox.mapboxsdk.constants; import android.support.annotation.StringDef; -import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.maps.MapView; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java index 00655800e..6abf9cf15 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java @@ -4,7 +4,7 @@ import android.graphics.Bitmap; import com.mapbox.mapboxsdk.annotations.Icon; import com.mapbox.mapboxsdk.annotations.Marker; -import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.maps.MapView; /** *

diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java index 889df322a..2e25082e1 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java @@ -1,7 +1,7 @@ package com.mapbox.mapboxsdk.exceptions; import android.os.Bundle; -import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.maps.MapView; /** * A {@code InvalidAccessTokenException} is thrown by {@link MapView} when there is either no access diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java new file mode 100644 index 000000000..9cfa5997c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java @@ -0,0 +1,296 @@ +package com.mapbox.mapboxsdk.geometry; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.List; + +/** + * An immutable class representing a latitude/longitude aligned rectangle. + */ +public class LatLngBounds implements Parcelable { + + private final double mLatNorth; + private final double mLatSouth; + private final double mLonEast; + private final double mLonWest; + + private final boolean mIsValid; + + /** + * Construct a new LatLngBounds based on its corners, given in NESW + * order. + * + * @param northLatitude Northern Latitude + * @param eastLongitude Eastern Longitude + * @param southLatitude Southern Latitude + * @param westLongitude Western Longitude + */ + public LatLngBounds(final double northLatitude, final double eastLongitude, final double southLatitude, final double westLongitude) { + this.mLatNorth = northLatitude; + this.mLonEast = eastLongitude; + this.mLatSouth = southLatitude; + this.mLonWest = westLongitude; + this.mIsValid = ((this.mLonWest < this.mLonEast) && (this.mLatNorth > this.mLatSouth)); + } + + /** + * Construct a new LatLngBounds based on its corners, given in NESW order. + * + * @param northEast Coordinate + * @param southWest Coordinate + */ + public LatLngBounds(final LatLng northEast, final LatLng southWest) { + this(northEast.getLatitude(), northEast.getLongitude(), southWest.getLatitude(), southWest.getLongitude()); + } + + /** + * Create a LatLngBounds box from another LatLngBounds + * + * @param other the other LatLngBounds + */ + public LatLngBounds(final LatLngBounds other) { + this.mLatNorth = other.getLatNorth(); + this.mLonEast = other.getLonEast(); + this.mLatSouth = other.getLatSouth(); + this.mLonWest = other.getLonWest(); + this.mIsValid = other.isValid(); + } + + /** + * Calculates the centerpoint of this LatLngBounds by simple interpolation and returns + * it as a point. This is a non-geodesic calculation which is not the geographic center. + * + * @return LatLng center of this LatLngBounds + */ + public LatLng getCenter() { + return new LatLng((this.mLatNorth + this.mLatSouth) / 2, + (this.mLonEast + this.mLonWest) / 2); + } + + public double getLatNorth() { + return this.mLatNorth; + } + + public double getLatSouth() { + return this.mLatSouth; + } + + public double getLonEast() { + return this.mLonEast; + } + + public double getLonWest() { + return this.mLonWest; + } + + public boolean isValid() { + return this.mIsValid; + } + + /** + * Get the area spanned by this LatLngBounds + * + * @return CoordinateSpan area + */ + public CoordinateSpan getSpan() { + return new CoordinateSpan(getLatitudeSpan(), getLongitudeSpan()); + } + + /** + * Get the absolute distance, in degrees, between the north and + * south boundaries of this LatLngBounds + * + * @return Span distance + */ + public double getLatitudeSpan() { + return Math.abs(this.mLatNorth - this.mLatSouth); + } + + /** + * Get the absolute distance, in degrees, between the west and + * east boundaries of this LatLngBounds + * + * @return Span distance + */ + public double getLongitudeSpan() { + return Math.abs(this.mLonEast - this.mLonWest); + } + + + /** + * Validate if LatLngBounds is empty, determined if absolute distance is + * + * @return boolean indicating if span is empty + */ + public boolean isEmpty() { + return getLongitudeSpan() == 0.0 || getLatitudeSpan() == 0.0; + } + + @Override + public String toString() { + return "N:" + this.mLatNorth + "; E:" + this.mLonEast + "; S:" + this.mLatSouth + "; W:" + this.mLonWest; + } + + /** + * Constructs a LatLngBounds that contains all of a list of LatLng + * objects. Empty lists will yield invalid LatLngBounds. + * + * @param latLngs List of LatLng objects + * @return LatLngBounds + */ + public static LatLngBounds fromLatLngs(final List latLngs) { + double minLat = 90, + minLon = 180, + maxLat = -90, + maxLon = -180; + + for (final ILatLng gp : latLngs) { + final double latitude = gp.getLatitude(); + final double longitude = gp.getLongitude(); + + minLat = Math.min(minLat, latitude); + minLon = Math.min(minLon, longitude); + maxLat = Math.max(maxLat, latitude); + maxLon = Math.max(maxLon, longitude); + } + + return new LatLngBounds(maxLat, maxLon, minLat, minLon); + } + + /** + * Determines whether this LatLngBounds matches another one via LatLng. + * + * @param o another object + * @return a boolean indicating whether the LatLngBounds are equal + */ + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o instanceof BoundingBox) { + BoundingBox other = (BoundingBox) o; + return mLatNorth == other.getLatNorth() + && mLatSouth == other.getLatSouth() + && mLonEast == other.getLonEast() + && mLonWest == other.getLonWest(); + } + return false; + } + + /** + * Determines whether this LatLngBounds contains a point and the point + * does not touch its boundary. + * + * @param latLng the point which may be contained + * @return true, if the point is contained within the box. + */ + public boolean contains(final ILatLng latLng) { + final double latitude = latLng.getLatitude(); + final double longitude = latLng.getLongitude(); + return ((latitude < this.mLatNorth) + && (latitude > this.mLatSouth)) + && ((longitude < this.mLonEast) + && (longitude > this.mLonWest)); + } + + /** + * Returns a new LatLngBounds that stretches to contain both this and another LatLngBounds. + * + * @param bounds LatLngBounds to add + * @return LatLngBounds + */ + public LatLngBounds union(LatLngBounds bounds) { + return union(bounds.getLatNorth(), bounds.getLonEast(), bounds.getLatSouth(), bounds.getLonWest()); + } + + /** + * Returns a new LatLngBounds that stretches to include another LatLngBounds, + * given by corner points. + * + * @param lonNorth Northern Longitude + * @param latEast Eastern Latitude + * @param lonSouth Southern Longitude + * @param latWest Western Longitude + * @return BoundingBox + */ + public LatLngBounds union(final double lonNorth, final double latEast, final double lonSouth, final double latWest) { + return new LatLngBounds((this.mLatNorth < lonNorth) ? lonNorth : this.mLatNorth, + (this.mLonEast < latEast) ? latEast : this.mLonEast, + (this.mLatSouth > lonSouth) ? lonSouth : this.mLatSouth, + (this.mLonWest > latWest) ? latWest : this.mLonWest); + } + + /** + * Returns a new LatLngBounds that is the intersection of this with another box + * + * @param box LatLngBounds to intersect with + * @return LatLngBounds + */ + public LatLngBounds intersect(LatLngBounds box) { + double minLatWest = Math.max(getLonWest(), box.getLonWest()); + double maxLatEast = Math.min(getLonEast(), box.getLonEast()); + if (maxLatEast > minLatWest) { + double minLonSouth = Math.max(getLatSouth(), box.getLatSouth()); + double maxLonNorth = Math.min(getLatNorth(), box.getLatNorth()); + if (maxLonNorth > minLonSouth) { + return new LatLngBounds(maxLonNorth, maxLatEast, minLonSouth, minLatWest); + } + } + return null; + } + + /** + * Returns a new LatLngBounds that is the intersection of this with another LatLngBounds + * + * @param northLongitude Northern Longitude + * @param eastLatitude Eastern Latitude + * @param southLongitude Southern Longitude + * @param westLatitude Western Latitude + * @return LatLngBounds + */ + public LatLngBounds intersect(double northLongitude, double eastLatitude, double southLongitude, double westLatitude) { + return intersect(new LatLngBounds(northLongitude, eastLatitude, southLongitude, westLatitude)); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public LatLngBounds createFromParcel(final Parcel in) { + return readFromParcel(in); + } + + @Override + public LatLngBounds[] newArray(final int size) { + return new LatLngBounds[size]; + } + }; + + @Override + public int hashCode() { + return (int) ((mLatNorth + 90) + + ((mLatSouth + 90) * 1000) + + ((mLonEast + 180) * 1000000) + + ((mLonEast + 180) * 1000000000)); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(final Parcel out, final int arg1) { + out.writeDouble(this.mLatNorth); + out.writeDouble(this.mLonEast); + out.writeDouble(this.mLatSouth); + out.writeDouble(this.mLonWest); + } + + private static LatLngBounds readFromParcel(final Parcel in) { + final double lonNorth = in.readDouble(); + final double latEast = in.readDouble(); + final double lonSouth = in.readDouble(); + final double latWest = in.readDouble(); + return new LatLngBounds(lonNorth, latEast, lonSouth, latWest); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngZoom.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngZoom.java deleted file mode 100644 index 6e24faaa9..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngZoom.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.mapbox.mapboxsdk.geometry; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.io.Serializable; - -/** - * A geographical location which contains a {@link LatLng}, zoom pair. - */ -public class LatLngZoom extends LatLng implements Parcelable { - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public LatLngZoom createFromParcel(Parcel in) { - return new LatLngZoom(in); - } - - public LatLngZoom[] newArray(int size) { - return new LatLngZoom[size]; - } - }; - - private double zoom; - - public LatLngZoom() { - super(); - this.zoom = 0.0; - } - - public LatLngZoom(double latitude, double longitude, double zoom) { - super(latitude, longitude); - this.zoom = zoom; - } - - public LatLngZoom(LatLng latLng, double zoom) { - super(latLng.getLatitude(), latLng.getLongitude()); - this.zoom = zoom; - } - - private LatLngZoom(Parcel in) { - super(in); - zoom = in.readDouble(); - } - - public double getZoom() { - return zoom; - } - - public void setZoom(double zoom) { - this.zoom = zoom; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - - LatLngZoom that = (LatLngZoom) o; - - return Double.compare(that.zoom, zoom) == 0; - - } - - @Override - public int hashCode() { - int result = super.hashCode(); - long temp; - temp = Double.doubleToLongBits(zoom); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public String toString() { - return "LatLngZoom [latitude=" + super.getLatitude() + ", longitude=" + super.getLongitude() + ", altitude=" + super.getAltitude() + ", zoom=" + zoom + "]"; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeDouble(zoom); - } - -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/CompassView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassView.java similarity index 98% rename from platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/CompassView.java rename to platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassView.java index 7bd07d093..0d8428933 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/CompassView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassView.java @@ -1,4 +1,4 @@ -package com.mapbox.mapboxsdk.views; +package com.mapbox.mapboxsdk.maps; import android.content.Context; import android.support.v4.content.ContextCompat; @@ -21,7 +21,7 @@ import java.util.TimerTask; * when it isn't true north (0.0). Tapping the compass resets the bearing to true * north and hides the compass. */ -final class CompassView extends ImageView { +public class CompassView extends ImageView { private Timer mNorthTimer; private double mDirection = 0.0f; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapFragment.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java similarity index 60% rename from platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapFragment.java rename to platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java index 572598996..0802245f4 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapFragment.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java @@ -1,14 +1,16 @@ -package com.mapbox.mapboxsdk; +package com.mapbox.mapboxsdk.maps; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.utils.ApiAccess; -import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.maps.MapView; /** * Fragment wrapper around a {@link MapView}. @@ -19,10 +21,10 @@ import com.mapbox.mapboxsdk.views.MapView; * using a FragmentManager. *

*

- * To get a reference to the MapView, use {@link #getMap()} + * To get a reference to the MapView, use {@link #getMapAsync(OnMapReadyCallback)}} *

* - * @see #getMap() + * @see #getMapAsync(OnMapReadyCallback) */ public class MapFragment extends Fragment { @@ -33,111 +35,86 @@ public class MapFragment extends Fragment { // Tag used for logging private static final String TAG = "MapFragment"; + // Argument used for configuration + private static final String ARGS_MAPBOXMAP_OPTIONS = "MapboxMapOptions"; + // // Instance members // // The map private MapView mMap; + private OnMapReadyCallback mMapReadyCallback; - // - // Lifecycle events - // + public static MapFragment newInstance(){ + return new MapFragment(); + } + + public static MapFragment newInstance(MapboxMapOptions mapboxMapOptions) { + final MapFragment mapFragment = new MapFragment(); + Bundle bundle = new Bundle(); + bundle.putParcelable(ARGS_MAPBOXMAP_OPTIONS, mapboxMapOptions); + mapFragment.setArguments(bundle); + return mapFragment; + } - // Called when the fragment is created @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); - Log.v(TAG, "onCreateView"); - - // Create the map mMap = (MapView) inflater.inflate(R.layout.fragment_mapview, container, false); - - // Set accessToken mMap.setAccessToken(ApiAccess.getToken(inflater.getContext())); - - // Need to pass on any saved state to the map mMap.onCreate(savedInstanceState); - - // Return the map as the root view return mMap; } - // Called when the fragment is destroyed - @Override - public void onDestroyView() { - super.onDestroyView(); - Log.v(TAG, "onDestroyView"); - - // Need to pass on to view - mMap.onDestroy(); - mMap = null; - } - - // Called when the fragment is visible @Override public void onStart() { super.onStart(); - Log.v(TAG, "onStart"); - - // Need to pass on to view mMap.onStart(); } - // Called when the fragment is invisible - @Override - public void onStop() { - super.onStop(); - Log.v(TAG, "onStop"); - - // Need to pass on to view - mMap.onStop(); - } - - // Called when the fragment is in the background - @Override - public void onPause() { - super.onPause(); - Log.v(TAG, "onPause"); - - // Need to pass on to view - mMap.onPause(); - } - - // Called when the fragment is no longer in the background @Override public void onResume() { super.onResume(); - Log.v(TAG, "onResume"); - - // Need to pass on to view mMap.onResume(); + if(mMapReadyCallback!=null){ + mMapReadyCallback.onMapReady(mMap.getMapboxMap()); + } } - // Called before fragment is destroyed @Override - public void onSaveInstanceState(Bundle outState) { - Log.v(TAG, "onSaveInstanceState"); + public void onPause() { + super.onPause(); + mMap.onPause(); + } - // Need to retrieve any saved state from the map + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { mMap.onSaveInstanceState(outState); super.onSaveInstanceState(outState); } @Override - public void onLowMemory() { - Log.v(TAG, "OnLowMemory"); + public void onStop() { + super.onStop(); + mMap.onStop(); + } - // Need to pass on to view + @Override + public void onLowMemory() { mMap.onLowMemory(); super.onLowMemory(); } - // - // Property methods - // + @Override + public void onDestroyView() { + super.onDestroyView(); + mMap.onDestroy(); + mMap = null; + } - public MapView getMap() { - return mMap; + @NonNull + public void getMapAsync(@NonNull OnMapReadyCallback onMapReadyCallback){ + mMapReadyCallback = onMapReadyCallback; } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java similarity index 56% rename from platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java rename to platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index b4ae08651..f47f30ee0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -1,8 +1,8 @@ -package com.mapbox.mapboxsdk.views; +package com.mapbox.mapboxsdk.maps; import android.Manifest; +import android.annotation.SuppressLint; import android.app.Activity; -import android.app.ActivityManager; import android.app.Dialog; import android.app.Fragment; import android.content.BroadcastReceiver; @@ -21,12 +21,10 @@ import android.location.Location; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.support.annotation.CallSuper; import android.support.annotation.FloatRange; import android.support.annotation.IntDef; -import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RequiresPermission; @@ -69,9 +67,8 @@ import com.mapbox.mapboxsdk.annotations.Polyline; import com.mapbox.mapboxsdk.annotations.PolylineOptions; import com.mapbox.mapboxsdk.annotations.IconFactory; import com.mapbox.mapboxsdk.camera.CameraPosition; -import com.mapbox.mapboxsdk.camera.CameraUpdate; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; -import com.mapbox.mapboxsdk.constants.MathConstants; +import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.constants.MyBearingTracking; import com.mapbox.mapboxsdk.constants.MyLocationTracking; import com.mapbox.mapboxsdk.constants.Style; @@ -80,10 +77,8 @@ import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException; import com.mapbox.mapboxsdk.geometry.BoundingBox; import com.mapbox.mapboxsdk.geometry.CoordinateBounds; import com.mapbox.mapboxsdk.geometry.LatLng; -import com.mapbox.mapboxsdk.geometry.LatLngZoom; import com.mapbox.mapboxsdk.layers.CustomLayer; import com.mapbox.mapboxsdk.utils.ApiAccess; -import com.mapbox.mapboxsdk.utils.MathUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -92,7 +87,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.concurrent.TimeUnit; /** *

@@ -110,102 +104,30 @@ import java.util.concurrent.TimeUnit; * * @see MapView#setAccessToken(String) */ -public final class MapView extends FrameLayout { +public class MapView extends FrameLayout { - // - // Static members - // - - // Used for logging private static final String TAG = "MapView"; - - // Used for animation - private static final long ANIMATION_DURATION = 300; - - // Used for saving instance state - private static final String STATE_CENTER_LATLNG = "centerLatLng"; - private static final String STATE_CENTER_DIRECTION = "centerDirection"; - private static final String STATE_ZOOM = "zoomLevel"; - private static final String STATE_TILT = "tilt"; - private static final String STATE_ZOOM_ENABLED = "zoomEnabled"; - private static final String STATE_SCROLL_ENABLED = "scrollEnabled"; - private static final String STATE_ROTATE_ENABLED = "rotateEnabled"; - private static final String STATE_TILT_ENABLED = "tiltEnabled"; - private static final String STATE_ZOOM_CONTROLS_ENABLED = "zoomControlsEnabled"; - private static final String STATE_DEBUG_ACTIVE = "debugActive"; - private static final String STATE_STYLE_URL = "styleUrl"; - private static final String STATE_ACCESS_TOKEN = "accessToken"; - private static final String STATE_STYLE_CLASSES = "styleClasses"; - private static final String STATE_DEFAULT_TRANSITION_DURATION = "defaultTransitionDuration"; - private static final String STATE_MY_LOCATION_ENABLED = "myLocationEnabled"; - private static final String STATE_MY_LOCATION_TRACKING_MODE = "myLocationTracking"; - private static final String STATE_MY_BEARING_TRACKING_MODE = "myBearingTracking"; - private static final String STATE_COMPASS_ENABLED = "compassEnabled"; - private static final String STATE_COMPASS_GRAVITY = "compassGravity"; - private static final String STATE_COMPASS_MARGIN_LEFT = "compassMarginLeft"; - private static final String STATE_COMPASS_MARGIN_TOP = "compassMarginTop"; - private static final String STATE_COMPASS_MARGIN_RIGHT = "compassMarginRight"; - private static final String STATE_COMPASS_MARGIN_BOTTOM = "compassMarginBottom"; - private static final String STATE_LOGO_GRAVITY = "logoGravity"; - private static final String STATE_LOGO_MARGIN_LEFT = "logoMarginLeft"; - private static final String STATE_LOGO_MARGIN_TOP = "logoMarginTop"; - private static final String STATE_LOGO_MARGIN_RIGHT = "logoMarginRight"; - private static final String STATE_LOGO_MARGIN_BOTTOM = "logoMarginBottom"; - private static final String STATE_LOGO_VISIBILITY = "logoVisibility"; - private static final String STATE_ATTRIBUTION_GRAVITY = "attrGravity"; - private static final String STATE_ATTRIBUTION_MARGIN_LEFT = "attrMarginLeft"; - private static final String STATE_ATTRIBUTION_MARGIN_TOP = "attrMarginTop"; - private static final String STATE_ATTRIBUTION_MARGIN_RIGHT = "attrMarginRight"; - private static final String STATE_ATTRIBUTION_MARGIN_BOTTOM = "atrrMarginBottom"; - private static final String STATE_ATTRIBUTION_VISIBILITY = "atrrVisibility"; - - // Used for positioning views 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_SEVENTYSIX_DP = 76f; - // Used to select "Improve this map" link in the attribution dialog - // Index into R.arrays.attribution_links - private static final int ATTRIBUTION_INDEX_IMPROVE_THIS_MAP = 2; + private MapboxMap mMapboxMap; + private List mAnnotations; + private List mIcons; - /** - * The currently supported maximum zoom level. - * - * @see MapView#setZoomLevel(double) - * @deprecated use #MAXIMUM_ZOOM instead. - */ - public static final double MAXIMUM_ZOOM_LEVEL = 18.0; - - /** - * The currently supported maximum zoom level. - * - * @see MapView#setZoom(double) - */ - public static final double MAXIMUM_ZOOM = 18.0; - - /** - * The currently supported maximum and minimum tilt values. - * - * @see MapView#setTilt(Double, Long) - */ - private static final double MINIMUM_TILT = 0; - private static final double MAXIMUM_TILT = 60; - - // - // Instance members - // - - // Used to call JNI NativeMapView private NativeMapView mNativeMapView; + private CompassView mCompassView; + private ImageView mLogoView; + private ImageView mAttributionsView; + private UserLocationView mUserLocationView; - // Used to track rendering - private TextureView mTextureView; - - // Used to handle DPI scaling + private List mOnMapChangedListener; + private ZoomButtonsController mZoomButtonsController; + private ConnectivityReceiver mConnectivityReceiver; private float mScreenDensity = 1.0f; - // Touch gesture detectors + private TrackballLongPressTimeOut mCurrentTrackballLongPressTimeOut; private GestureDetectorCompat mGestureDetector; private ScaleGestureDetector mScaleGestureDetector; private RotateGestureDetector mRotateGestureDetector; @@ -214,543 +136,37 @@ public final class MapView extends FrameLayout { private boolean mZoomStarted = false; private boolean mQuickZoom = false; - // Shows zoom buttons - private ZoomButtonsController mZoomButtonsController; - private boolean mZoomControlsEnabled = false; - - // Used to track trackball long presses - private TrackballLongPressTimeOut mCurrentTrackballLongPressTimeOut; - - // Receives changes to network connectivity - private ConnectivityReceiver mConnectivityReceiver; - - // Used for user location - private UserLocationView mUserLocationView; - - // Used for the compass - private CompassView mCompassView; - - // Used for displaying annotations - // Every annotation that has been added to the map - private final List mAnnotations = new ArrayList<>(); - private List mMarkersNearLastTap = new ArrayList<>(); - private List mSelectedMarkers = new ArrayList<>(); - private List mInfoWindows = new ArrayList<>(); - private InfoWindowAdapter mInfoWindowAdapter; - private List mIcons = new ArrayList<>(); - - // Used for the Mapbox Logo - private ImageView mLogoView; - - // Used for attributions control - private ImageView mAttributionsView; - - // Used to manage MapChange event listeners - private List mOnMapChangedListener = new ArrayList<>(); - - // Used to manage map click event listeners - private OnMapClickListener mOnMapClickListener; - private OnMapLongClickListener mOnMapLongClickListener; - - // Used to manage fling and scroll event listeners - private OnFlingListener mOnFlingListener; - private OnScrollListener mOnScrollListener; - - // Used to manage marker click event listeners - private OnMarkerClickListener mOnMarkerClickListener; - private OnInfoWindowClickListener mOnInfoWindowClickListener; - - // Used to manage FPS change event listeners - private OnFpsChangedListener mOnFpsChangedListener; - - // Used to manage tracking mode changes - private OnMyLocationTrackingModeChangeListener mOnMyLocationTrackingModeChangeListener; - private OnMyBearingTrackingModeChangeListener mOnMyBearingTrackingModeChangeListener; - - // - // Properties - // - - // These are properties with setters/getters, saved in onSaveInstanceState and XML attributes - private boolean mZoomEnabled = true; - private boolean mScrollEnabled = true; - private boolean mRotateEnabled = true; - private boolean mTiltEnabled = true; - private boolean mAllowConcurrentMultipleOpenInfoWindows = false; - private String mStyleUrl; - -/* + /* private int mContentPaddingLeft; private int mContentPaddingTop; private int mContentPaddingRight; private int mContentPaddingBottom; */ - // - // Inner classes - // - - // - // Enums - // - - /** - * Map change event types. - * - * @see MapView.OnMapChangedListener#onMapChanged(int) - */ - @IntDef({REGION_WILL_CHANGE, - REGION_WILL_CHANGE_ANIMATED, - REGION_IS_CHANGING, - REGION_DID_CHANGE, - REGION_DID_CHANGE_ANIMATED, - WILL_START_LOADING_MAP, - DID_FINISH_LOADING_MAP, - DID_FAIL_LOADING_MAP, - WILL_START_RENDERING_FRAME, - DID_FINISH_RENDERING_FRAME, - DID_FINISH_RENDERING_FRAME_FULLY_RENDERED, - WILL_START_RENDERING_MAP, - DID_FINISH_RENDERING_MAP, - DID_FINISH_RENDERING_MAP_FULLY_RENDERED - }) - @Retention(RetentionPolicy.SOURCE) - public @interface MapChange { - } - - /** - *

- * This {@link MapChange} is triggered whenever the currently displayed map region is about to changing - * without an animation. - *

- *

- * This event is followed by a series of {@link MapView#REGION_IS_CHANGING} and ends - * with {@link MapView#REGION_DID_CHANGE}. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int REGION_WILL_CHANGE = 0; - - /** - *

- * This {@link MapChange} is triggered whenever the currently displayed map region is about to changing - * with an animation. - *

- *

- * This event is followed by a series of {@link MapView#REGION_IS_CHANGING} and ends - * with {@link MapView#REGION_DID_CHANGE_ANIMATED}. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int REGION_WILL_CHANGE_ANIMATED = 1; - - /** - *

- * This {@link MapChange} is triggered whenever the currently displayed map region is changing. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int REGION_IS_CHANGING = 2; - - /** - *

- * This {@link MapChange} is triggered whenever the currently displayed map region finished changing - * without an animation. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int REGION_DID_CHANGE = 3; - - /** - *

- * This {@link MapChange} is triggered whenever the currently displayed map region finished changing - * with an animation. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int REGION_DID_CHANGE_ANIMATED = 4; - - /** - *

- * This {@link MapChange} is triggered when the map is about to start loading a new map style. - *

- *

- * This event is followed by {@link MapView#DID_FINISH_LOADING_MAP} or - * {@link MapView#DID_FAIL_LOADING_MAP}. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int WILL_START_LOADING_MAP = 5; - - /** - *

- * This {@link MapChange} is triggered when the map has successfully loaded a new map style. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int DID_FINISH_LOADING_MAP = 6; - - /** - *

- * This {@link MapChange} is currently not implemented. - *

- *

- * This event is triggered when the map has failed to load a new map style. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int DID_FAIL_LOADING_MAP = 7; - - /** - *

- * This {@link MapChange} is currently not implemented. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int WILL_START_RENDERING_FRAME = 8; - - /** - *

- * This {@link MapChange} is currently not implemented. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int DID_FINISH_RENDERING_FRAME = 9; - - /** - *

- * This {@link MapChange} is currently not implemented. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int DID_FINISH_RENDERING_FRAME_FULLY_RENDERED = 10; - - /** - *

- * This {@link MapChange} is currently not implemented. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int WILL_START_RENDERING_MAP = 11; - - /** - *

- * This {@link MapChange} is currently not implemented. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int DID_FINISH_RENDERING_MAP = 12; - - /** - *

- * This {@link MapChange} is currently not implemented. - *

- * - * @see com.mapbox.mapboxsdk.views.MapView.OnMapChangedListener - */ - public static final int DID_FINISH_RENDERING_MAP_FULLY_RENDERED = 13; - - // - // Interfaces - // - - /** - * Interface definition for a callback to be invoked when the map is flinged. - * - * @see MapView#setOnFlingListener(OnFlingListener) - */ - public interface OnFlingListener { - /** - * Called when the map is flinged. - */ - void onFling(); - } - - /** - * Interface definition for a callback to be invoked when the map is scrolled. - * - * @see MapView#setOnScrollListener(OnScrollListener) - */ - public interface OnScrollListener { - /** - * Called when the map is scrolled. - */ - void onScroll(); - } - - /** - * Interface definition for a callback to be invoked on every frame rendered to the map view. - * - * @see MapView#setOnFpsChangedListener(OnFpsChangedListener) - */ - public interface OnFpsChangedListener { - /** - * Called for every frame rendered to the map view. - * - * @param fps The average number of frames rendered over the last second. - */ - void onFpsChanged(double fps); - } - - /** - * Interface definition for a callback to be invoked when the user clicks on the map view. - * - * @see MapView#setOnMapClickListener(OnMapClickListener) - */ - public interface OnMapClickListener { - /** - * Called when the user clicks on the map view. - * - * @param point The projected map coordinate the user clicked on. - */ - void onMapClick(@NonNull LatLng point); - } - - /** - * Interface definition for a callback to be invoked when the user long clicks on the map view. - * - * @see MapView#setOnMapLongClickListener(OnMapLongClickListener) - */ - public interface OnMapLongClickListener { - /** - * Called when the user long clicks on the map view. - * - * @param point The projected map coordinate the user long clicked on. - */ - void onMapLongClick(@NonNull LatLng point); - } - - /** - * Interface definition for a callback to be invoked when the user clicks on a marker. - * - * @see MapView#setOnMarkerClickListener(OnMarkerClickListener) - */ - public interface OnMarkerClickListener { - /** - * Called when the user clicks on a marker. - * - * @param marker The marker the user clicked on. - * @return If true the listener has consumed the event and the info window will not be shown. - */ - boolean onMarkerClick(@NonNull Marker marker); - } - - /** - * Interface definition for a callback to be invoked when the user clicks on an info window. - * - * @see MapView#setOnInfoWindowClickListener(OnInfoWindowClickListener) - */ - public interface OnInfoWindowClickListener { - /** - * Called when the user clicks on an info window. - * - * @param marker The marker of the info window the user clicked on. - * @return If true the listener has consumed the event and the info window will not be closed. - */ - boolean onMarkerClick(@NonNull Marker marker); - } - - /** - * Interface definition for a callback to be invoked when the displayed map view changes. - * - * @see MapView#addOnMapChangedListener(OnMapChangedListener) - * @see MapView.MapChange - */ - public interface OnMapChangedListener { - /** - * Called when the displayed map view changes. - * - * @param change Type of map change event, one of {@link #REGION_WILL_CHANGE}, - * {@link #REGION_WILL_CHANGE_ANIMATED}, - * {@link #REGION_IS_CHANGING}, - * {@link #REGION_DID_CHANGE}, - * {@link #REGION_DID_CHANGE_ANIMATED}, - * {@link #WILL_START_LOADING_MAP}, - * {@link #DID_FAIL_LOADING_MAP}, - * {@link #DID_FINISH_LOADING_MAP}, - * {@link #WILL_START_RENDERING_FRAME}, - * {@link #DID_FINISH_RENDERING_FRAME}, - * {@link #DID_FINISH_RENDERING_FRAME_FULLY_RENDERED}, - * {@link #WILL_START_RENDERING_MAP}, - * {@link #DID_FINISH_RENDERING_MAP}, - * {@link #DID_FINISH_RENDERING_MAP_FULLY_RENDERED}. - */ - void onMapChanged(@MapChange int change); - } - - /** - * Interface definition for a callback to be invoked when an info window will be shown. - * - * @see MapView#setInfoWindowAdapter(InfoWindowAdapter) - */ - public interface InfoWindowAdapter { - /** - * Called when an info window will be shown as a result of a marker click. - * - * @param marker The marker the user clicked on. - * @return View to be shown as a info window. If null is returned the default - * info window will be shown. - */ - @Nullable - View getInfoWindow(@NonNull Marker marker); - } - - /** - * Interface definition for a callback to be invoked when the the My Location dot - * (which signifies the user's location) changes location. - * - * @see MapView#setOnMyLocationChangeListener(OnMyLocationChangeListener) - */ - public interface OnMyLocationChangeListener { - /** - * Called when the location of the My Location dot has changed - * (be it latitude/longitude, bearing or accuracy). - * - * @param location The current location of the My Location dot The type of map change event. - */ - void onMyLocationChange(@Nullable Location location); - } - - /** - * Interface definition for a callback to be invoked when the the My Location tracking mode changes. - * - * @see MapView#setMyLocationTrackingMode(int) - */ - public interface OnMyLocationTrackingModeChangeListener { - - /** - * Called when the tracking mode of My Location tracking has changed - * - * @param myLocationTrackingMode the current active location tracking mode - */ - void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode); - } - - /** - * Interface definition for a callback to be invoked when the the My Location tracking mode changes. - * - * @see MapView#setMyLocationTrackingMode(int) - */ - public interface OnMyBearingTrackingModeChangeListener { - - /** - * Called when the tracking mode of My Bearing tracking has changed - * - * @param myBearingTrackingMode the current active bearing tracking mode - */ - void onMyBearingTrackingModeChange(@MyBearingTracking.Mode int myBearingTrackingMode); - } - - /** - * A callback interface for reporting when a task is complete or cancelled. - */ - public interface CancelableCallback { - /** - * Invoked when a task is cancelled. - */ - void onCancel(); - - /** - * Invoked when a task is complete. - */ - void onFinish(); - } - - // - // Constructors - // - - /** - * Simple constructor to use when creating a {@link MapView} from code using the default map style. - * - * @param context The {@link Context} of the {@link android.app.Activity} - * or {@link android.app.Fragment} the {@link MapView} is running in. - * @param accessToken Your public Mapbox access token. Used to load map styles and tiles. - */ @UiThread - public MapView(@NonNull Context context, @NonNull String accessToken) { + public MapView(@NonNull Context context) { super(context); - if (accessToken == null) { - Log.w(TAG, "accessToken was null, so just returning"); - return; - } initialize(context, null); - setAccessToken(accessToken); - setStyleUrl(null); } - /** - * Simple constructor to use when creating a {@link MapView} from code using the provided map style URL. - * - * @param context The {@link Context} of the {@link android.app.Activity} - * or {@link android.app.Fragment} the {@link MapView} is running in. - * @param accessToken Your public Mapbox access token. Used to load map styles and tiles. - * @param styleUrl A URL to the map style initially displayed. See {@link MapView#setStyleUrl(String)} for possible values. - * @see MapView#setStyleUrl(String) - */ - @UiThread - public MapView(@NonNull Context context, @NonNull String accessToken, @NonNull String styleUrl) { - super(context); - if (accessToken == null) { - Log.w(TAG, "accessToken was null, so just returning"); - return; - } - if (styleUrl == null) { - Log.w(TAG, "styleUrl was null, so just returning"); - return; - } - initialize(context, null); - setAccessToken(accessToken); - setStyleUrl(styleUrl); - } - - // Constructor that is called when inflating a view from XML. - - /** - * Do not call from code. - */ @UiThread public MapView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); initialize(context, attrs); } - // Constructor that is called when inflating a view from XML. - - /** - * Do not call from code. - */ @UiThread public MapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initialize(context, attrs); } - // - // Initialization - // + private void initialize(@NonNull Context context, @Nullable AttributeSet attrs) { + mMapboxMap = new MapboxMap(this); + mAnnotations = new ArrayList<>(); + mIcons = new ArrayList<>(); + mOnMapChangedListener = new ArrayList<>(); - // Common initialization code goes here - private void initialize(Context context, AttributeSet attrs) { - if (context == null) { - Log.w(TAG, "context was null, so just returning"); - return; - } - - // Inflate content View view = LayoutInflater.from(context).inflate(R.layout.mapview_internal, this); if (!isInEditMode()) { @@ -758,34 +174,15 @@ public final class MapView extends FrameLayout { } // Reference the TextureView - mTextureView = (TextureView) view.findViewById(R.id.textureView); - mTextureView.setSurfaceTextureListener(new SurfaceTextureListener()); + TextureView textureView = (TextureView) view.findViewById(R.id.textureView); + textureView.setSurfaceTextureListener(new SurfaceTextureListener()); // Check if we are in Android Studio UI editor to avoid error in layout preview if (isInEditMode()) { return; } - // Get the screen's density - mScreenDensity = context.getResources().getDisplayMetrics().density; - - // Get the cache path - String cachePath = context.getCacheDir().getAbsolutePath(); - String dataPath = context.getFilesDir().getAbsolutePath(); - String apkPath = context.getPackageCodePath(); - - // Create the NativeMapView - int availableProcessors = Runtime.getRuntime().availableProcessors(); - ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); - ActivityManager activityManager = (ActivityManager) context - .getSystemService(Context.ACTIVITY_SERVICE); - activityManager.getMemoryInfo(memoryInfo); - long maxMemory = memoryInfo.availMem; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - maxMemory = memoryInfo.totalMem; - } - mNativeMapView = new - NativeMapView(this, cachePath, dataPath, apkPath, mScreenDensity, availableProcessors, maxMemory); + mNativeMapView = new NativeMapView(this); // Ensure this view is interactable setClickable(true); @@ -805,92 +202,74 @@ public final class MapView extends FrameLayout { // Shows the zoom controls if (!context.getPackageManager() .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) { - mZoomControlsEnabled = true; + mMapboxMap.setZoomControlsEnabled(true); } mZoomButtonsController = new ZoomButtonsController(this); - mZoomButtonsController.setZoomSpeed(ANIMATION_DURATION); + mZoomButtonsController.setZoomSpeed(MapboxConstants.ANIMATION_DURATION); mZoomButtonsController.setOnZoomListener(new OnZoomListener()); - // Check current connection status - ConnectivityManager connectivityManager = (ConnectivityManager) context.getApplicationContext() - .getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo(); - boolean isConnected = (activeNetwork != null) && activeNetwork.isConnectedOrConnecting(); - onConnectivityChanged(isConnected); + // Connectivity + onConnectivityChanged(isConnected()); - // Setup user location UI mUserLocationView = (UserLocationView) view.findViewById(R.id.userLocationView); mUserLocationView.setMapView(this); - - // Setup compass mCompassView = (CompassView) view.findViewById(R.id.compassView); mCompassView.setOnClickListener(new CompassView.CompassClickListener(this)); - - // Setup Mapbox logo mLogoView = (ImageView) view.findViewById(R.id.logoView); // Setup Attributions control mAttributionsView = (ImageView) view.findViewById(R.id.attributionView); mAttributionsView.setOnClickListener(new AttributionOnClickListener(this)); + mScreenDensity = context.getResources().getDisplayMetrics().density; + // Load the attributes TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MapView, 0, 0); try { - double centerLatitude = typedArray.getFloat(R.styleable.MapView_center_latitude, 0.0f); - double centerLongitude = typedArray.getFloat(R.styleable.MapView_center_longitude, 0.0f); - setLatLng(new LatLng(centerLatitude, centerLongitude)); - // need to set zoom level first because of limitation on rotating when zoomed out - float zoom = typedArray.getFloat(R.styleable.MapView_zoom, 0.0f); - if(zoom != 0.0f){ - setZoom(zoom); - }else{ - setZoomLevel(typedArray.getFloat(R.styleable.MapView_zoom_level, 0.0f)); - } + // Debug mode + mMapboxMap.setDebugActive(typedArray.getBoolean(R.styleable.MapView_debug_active, false)); - setDirection(typedArray.getFloat(R.styleable.MapView_direction, 0.0f)); - setZoomEnabled(typedArray.getBoolean(R.styleable.MapView_zoom_enabled, true)); - setScrollEnabled(typedArray.getBoolean(R.styleable.MapView_scroll_enabled, true)); - setRotateEnabled(typedArray.getBoolean(R.styleable.MapView_rotate_enabled, true)); - setTiltEnabled(typedArray.getBoolean(R.styleable.MapView_tilt_enabled, true)); - setZoomControlsEnabled(typedArray.getBoolean(R.styleable.MapView_zoom_controls_enabled, isZoomControlsEnabled())); - setDebugActive(typedArray.getBoolean(R.styleable.MapView_debug_active, false)); - if (typedArray.getString(R.styleable.MapView_style_url) != null) { - setStyleUrl(typedArray.getString(R.styleable.MapView_style_url)); - } + // Move camera + CameraPosition cameraPosition = new CameraPosition.Builder(typedArray).build(); + mMapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); + + // Access token if (typedArray.getString(R.styleable.MapView_access_token) != null) { setAccessToken(typedArray.getString(R.styleable.MapView_access_token)); } - if (typedArray.getString(R.styleable.MapView_style_classes) != null) { - List styleClasses = Arrays.asList(typedArray - .getString(R.styleable.MapView_style_classes).split("\\s*,\\s*")); - for (String styleClass : styleClasses) { - if (styleClass.length() == 0) { - styleClasses.remove(styleClass); - } - } - setStyleClasses(styleClasses); + + // Style url + if (typedArray.getString(R.styleable.MapView_style_url) != null) { + mMapboxMap.setStyleUrl(typedArray.getString(R.styleable.MapView_style_url)); } + // Enable gestures + mMapboxMap.setZoomEnabled(typedArray.getBoolean(R.styleable.MapView_zoom_enabled, true)); + mMapboxMap.setScrollEnabled(typedArray.getBoolean(R.styleable.MapView_scroll_enabled, true)); + mMapboxMap.setRotateEnabled(typedArray.getBoolean(R.styleable.MapView_rotate_enabled, true)); + mMapboxMap.setTiltEnabled(typedArray.getBoolean(R.styleable.MapView_tilt_enabled, true)); + mMapboxMap.setZoomControlsEnabled(typedArray.getBoolean(R.styleable.MapView_zoom_controls_enabled, mMapboxMap.isZoomControlsEnabled())); + // Compass - setCompassEnabled(typedArray.getBoolean(R.styleable.MapView_compass_enabled, true)); - setCompassGravity(typedArray.getInt(R.styleable.MapView_compass_gravity, Gravity.TOP | Gravity.END)); + mMapboxMap.setCompassEnabled(typedArray.getBoolean(R.styleable.MapView_compass_enabled, true)); + mMapboxMap.setCompassGravity(typedArray.getInt(R.styleable.MapView_compass_gravity, Gravity.TOP | Gravity.END)); setWidgetMargins(mCompassView, typedArray.getDimension(R.styleable.MapView_compass_margin_left, DIMENSION_TEN_DP) , typedArray.getDimension(R.styleable.MapView_compass_margin_top, DIMENSION_TEN_DP) , typedArray.getDimension(R.styleable.MapView_compass_margin_right, DIMENSION_TEN_DP) , typedArray.getDimension(R.styleable.MapView_compass_margin_bottom, DIMENSION_TEN_DP)); // Logo - setLogoVisibility(typedArray.getInt(R.styleable.MapView_logo_visibility, View.VISIBLE)); - setLogoGravity(typedArray.getInt(R.styleable.MapView_logo_gravity, Gravity.BOTTOM | Gravity.START)); + mMapboxMap.setLogoVisibility(typedArray.getInt(R.styleable.MapView_logo_visibility, View.VISIBLE)); + mMapboxMap.setLogoGravity(typedArray.getInt(R.styleable.MapView_logo_gravity, Gravity.BOTTOM | Gravity.START)); setWidgetMargins(mLogoView, typedArray.getDimension(R.styleable.MapView_logo_margin_left, DIMENSION_SIXTEEN_DP) , typedArray.getDimension(R.styleable.MapView_logo_margin_top, DIMENSION_SIXTEEN_DP) , typedArray.getDimension(R.styleable.MapView_logo_margin_right, DIMENSION_SIXTEEN_DP) , typedArray.getDimension(R.styleable.MapView_logo_margin_bottom, DIMENSION_SIXTEEN_DP)); // Attribution - setAttributionVisibility(typedArray.getInt(R.styleable.MapView_attribution_visibility, View.VISIBLE)); - setAttributionGravity(typedArray.getInt(R.styleable.MapView_attribution_gravity, Gravity.BOTTOM)); + mMapboxMap.setAttributionVisibility(typedArray.getInt(R.styleable.MapView_attribution_visibility, View.VISIBLE)); + mMapboxMap.setAttributionGravity(typedArray.getInt(R.styleable.MapView_attribution_gravity, Gravity.BOTTOM)); setWidgetMargins(mAttributionsView, typedArray.getDimension(R.styleable.MapView_attribution_margin_left, DIMENSION_SEVENTYSIX_DP) , typedArray.getDimension(R.styleable.MapView_attribution_margin_top, DIMENSION_SEVEN_DP) , typedArray.getDimension(R.styleable.MapView_attribution_margin_right, DIMENSION_SEVEN_DP) @@ -899,8 +278,8 @@ public final class MapView extends FrameLayout { // User location try { //noinspection ResourceType - setMyLocationEnabled(typedArray.getBoolean(R.styleable.MapView_my_location_enabled, false)); - }catch (SecurityException ignore){ + mMapboxMap.setMyLocationEnabled(typedArray.getBoolean(R.styleable.MapView_my_location_enabled, false)); + } catch (SecurityException ignore) { // User did not accept location permissions } @@ -927,62 +306,59 @@ public final class MapView extends FrameLayout { @UiThread public void onCreate(@Nullable Bundle savedInstanceState) { if (savedInstanceState != null) { - setLatLng((LatLng) savedInstanceState.getParcelable(STATE_CENTER_LATLNG)); - // need to set zoom level first because of limitation on rotating when zoomed out - setZoom(savedInstanceState.getDouble(STATE_ZOOM)); - setDirection(savedInstanceState.getDouble(STATE_CENTER_DIRECTION)); - setTilt(savedInstanceState.getDouble(STATE_TILT), null); - setZoomEnabled(savedInstanceState.getBoolean(STATE_ZOOM_ENABLED)); - setScrollEnabled(savedInstanceState.getBoolean(STATE_SCROLL_ENABLED)); - setRotateEnabled(savedInstanceState.getBoolean(STATE_ROTATE_ENABLED)); - setTiltEnabled(savedInstanceState.getBoolean(STATE_TILT_ENABLED)); - setZoomControlsEnabled(savedInstanceState.getBoolean(STATE_ZOOM_CONTROLS_ENABLED)); - setDebugActive(savedInstanceState.getBoolean(STATE_DEBUG_ACTIVE)); - setStyleUrl(savedInstanceState.getString(STATE_STYLE_URL)); - setAccessToken(savedInstanceState.getString(STATE_ACCESS_TOKEN)); - List appliedStyleClasses = savedInstanceState.getStringArrayList(STATE_STYLE_CLASSES); - if (!appliedStyleClasses.isEmpty()) { - setStyleClasses(appliedStyleClasses); + + // Get previous camera position + CameraPosition cameraPosition = savedInstanceState.getParcelable(MapboxConstants.STATE_CAMERA_POSITION); + if (cameraPosition != null) { + mMapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); } + mMapboxMap.setZoomEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_ENABLED)); + mMapboxMap.setScrollEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_SCROLL_ENABLED)); + mMapboxMap.setRotateEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ENABLED)); + mMapboxMap.setTiltEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_TILT_ENABLED)); + mMapboxMap.setZoomControlsEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED)); + mMapboxMap.setDebugActive(savedInstanceState.getBoolean(MapboxConstants.STATE_DEBUG_ACTIVE)); + mMapboxMap.setStyleUrl(savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL)); + setAccessToken(savedInstanceState.getString(MapboxConstants.STATE_ACCESS_TOKEN)); mNativeMapView.setDefaultTransitionDuration( - savedInstanceState.getLong(STATE_DEFAULT_TRANSITION_DURATION)); + savedInstanceState.getLong(MapboxConstants.STATE_DEFAULT_TRANSITION_DURATION)); // User location try { //noinspection ResourceType - setMyLocationEnabled(savedInstanceState.getBoolean(STATE_MY_LOCATION_ENABLED)); - }catch (SecurityException ignore){ + mMapboxMap.setMyLocationEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED)); + } catch (SecurityException ignore) { // User did not accept location permissions } // Compass - setCompassEnabled(savedInstanceState.getBoolean(STATE_COMPASS_ENABLED)); - setCompassGravity(savedInstanceState.getInt(STATE_COMPASS_GRAVITY)); - setCompassMargins(savedInstanceState.getInt(STATE_COMPASS_MARGIN_LEFT) - , savedInstanceState.getInt(STATE_COMPASS_MARGIN_TOP) - , savedInstanceState.getInt(STATE_COMPASS_MARGIN_RIGHT) - , savedInstanceState.getInt(STATE_COMPASS_MARGIN_BOTTOM)); + mMapboxMap.setCompassEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_COMPASS_ENABLED)); + mMapboxMap.setCompassGravity(savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_GRAVITY)); + mMapboxMap.setCompassMargins(savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_LEFT) + , savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP) + , savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT) + , savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM)); // Logo - setLogoVisibility(savedInstanceState.getInt(STATE_LOGO_VISIBILITY)); - setLogoGravity(savedInstanceState.getInt(STATE_LOGO_GRAVITY)); - setLogoMargins(savedInstanceState.getInt(STATE_LOGO_MARGIN_LEFT) - , savedInstanceState.getInt(STATE_LOGO_MARGIN_TOP) - , savedInstanceState.getInt(STATE_LOGO_MARGIN_RIGHT) - , savedInstanceState.getInt(STATE_LOGO_MARGIN_BOTTOM)); + mMapboxMap.setLogoVisibility(savedInstanceState.getInt(MapboxConstants.STATE_LOGO_VISIBILITY)); + mMapboxMap.setLogoGravity(savedInstanceState.getInt(MapboxConstants.STATE_LOGO_GRAVITY)); + mMapboxMap.setLogoMargins(savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_LEFT) + , savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_TOP) + , savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_RIGHT) + , savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_BOTTOM)); // Attribution - setAttributionVisibility(savedInstanceState.getInt(STATE_ATTRIBUTION_VISIBILITY)); - setAttributionGravity(savedInstanceState.getInt(STATE_ATTRIBUTION_GRAVITY)); - setAttributionMargins(savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_LEFT) - , savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_TOP) - , savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_RIGHT) - , savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_BOTTOM)); + mMapboxMap.setAttributionVisibility(savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_VISIBILITY)); + mMapboxMap.setAttributionGravity(savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_GRAVITY)); + mMapboxMap.setAttributionMargins(savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_LEFT) + , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_TOP) + , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_RIGHT) + , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM)); //noinspection ResourceType - setMyLocationTrackingMode(savedInstanceState.getInt(STATE_MY_LOCATION_TRACKING_MODE, MyLocationTracking.TRACKING_NONE)); + mMapboxMap.setMyLocationTrackingMode(savedInstanceState.getInt(MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE, MyLocationTracking.TRACKING_NONE)); //noinspection ResourceType - setMyBearingTrackingMode(savedInstanceState.getInt(STATE_MY_BEARING_TRACKING_MODE, MyBearingTracking.NONE)); + mMapboxMap.setMyBearingTrackingMode(savedInstanceState.getInt(MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, MyBearingTracking.NONE)); } // Force a check for an access token @@ -1011,58 +387,49 @@ public final class MapView extends FrameLayout { * * @param outState Pass in the parent's outState. */ + @UiThread public void onSaveInstanceState(@NonNull Bundle outState) { - if (outState == null) { - Log.w(TAG, "outState was null, so just returning"); - return; - } - - outState.putParcelable(STATE_CENTER_LATLNG, getLatLng()); - // need to set zoom level first because of limitation on rotating when zoomed out - outState.putDouble(STATE_ZOOM, getZoom()); - outState.putDouble(STATE_CENTER_DIRECTION, getDirection()); - outState.putDouble(STATE_TILT, getTilt()); - outState.putBoolean(STATE_ZOOM_ENABLED, isZoomEnabled()); - outState.putBoolean(STATE_SCROLL_ENABLED, isScrollEnabled()); - outState.putBoolean(STATE_ROTATE_ENABLED, isRotateEnabled()); - outState.putBoolean(STATE_TILT_ENABLED, isTiltEnabled()); - outState.putBoolean(STATE_ZOOM_CONTROLS_ENABLED, isZoomControlsEnabled()); - outState.putBoolean(STATE_DEBUG_ACTIVE, isDebugActive()); - outState.putString(STATE_STYLE_URL, getStyleUrl()); - outState.putString(STATE_ACCESS_TOKEN, getAccessToken()); - outState.putStringArrayList(STATE_STYLE_CLASSES, new ArrayList<>(getStyleClasses())); - outState.putLong(STATE_DEFAULT_TRANSITION_DURATION, mNativeMapView.getDefaultTransitionDuration()); - outState.putBoolean(STATE_MY_LOCATION_ENABLED, isMyLocationEnabled()); - outState.putInt(STATE_MY_LOCATION_TRACKING_MODE, mUserLocationView.getMyLocationTrackingMode()); - outState.putInt(STATE_MY_BEARING_TRACKING_MODE, mUserLocationView.getMyBearingTrackingMode()); + outState.putParcelable(MapboxConstants.STATE_CAMERA_POSITION, mMapboxMap.getCameraPosition()); + outState.putBoolean(MapboxConstants.STATE_ZOOM_ENABLED, mMapboxMap.isZoomEnabled()); + outState.putBoolean(MapboxConstants.STATE_SCROLL_ENABLED, mMapboxMap.isScrollEnabled()); + outState.putBoolean(MapboxConstants.STATE_ROTATE_ENABLED, mMapboxMap.isRotateEnabled()); + outState.putBoolean(MapboxConstants.STATE_TILT_ENABLED, mMapboxMap.isTiltEnabled()); + outState.putBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED, mMapboxMap.isZoomControlsEnabled()); + outState.putBoolean(MapboxConstants.STATE_DEBUG_ACTIVE, mMapboxMap.isDebugActive()); + outState.putString(MapboxConstants.STATE_STYLE_URL, mMapboxMap.getStyleUrl()); + outState.putString(MapboxConstants.STATE_ACCESS_TOKEN, mMapboxMap.getAccessToken()); + outState.putLong(MapboxConstants.STATE_DEFAULT_TRANSITION_DURATION, mNativeMapView.getDefaultTransitionDuration()); + outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED, mMapboxMap.isMyLocationEnabled()); + outState.putInt(MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE, mMapboxMap.getMyLocationTrackingMode()); + outState.putInt(MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, mMapboxMap.getMyBearingTrackingMode()); // Compass LayoutParams compassParams = (LayoutParams) mCompassView.getLayoutParams(); - outState.putBoolean(STATE_COMPASS_ENABLED, isCompassEnabled()); - outState.putInt(STATE_COMPASS_GRAVITY, compassParams.gravity); - outState.putInt(STATE_COMPASS_MARGIN_LEFT, compassParams.leftMargin); - outState.putInt(STATE_COMPASS_MARGIN_TOP, compassParams.topMargin); - outState.putInt(STATE_COMPASS_MARGIN_BOTTOM, compassParams.bottomMargin); - outState.putInt(STATE_COMPASS_MARGIN_RIGHT, compassParams.rightMargin); + outState.putBoolean(MapboxConstants.STATE_COMPASS_ENABLED, mMapboxMap.isCompassEnabled()); + outState.putInt(MapboxConstants.STATE_COMPASS_GRAVITY, compassParams.gravity); + outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_LEFT, compassParams.leftMargin); + outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP, compassParams.topMargin); + outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM, compassParams.bottomMargin); + outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT, compassParams.rightMargin); // Logo LayoutParams logoParams = (LayoutParams) mLogoView.getLayoutParams(); - outState.putInt(STATE_LOGO_GRAVITY, logoParams.gravity); - outState.putInt(STATE_LOGO_MARGIN_LEFT, logoParams.leftMargin); - outState.putInt(STATE_LOGO_MARGIN_TOP, logoParams.topMargin); - outState.putInt(STATE_LOGO_MARGIN_RIGHT, logoParams.rightMargin); - outState.putInt(STATE_LOGO_MARGIN_BOTTOM, logoParams.bottomMargin); - outState.putInt(STATE_LOGO_VISIBILITY, mLogoView.getVisibility()); + outState.putInt(MapboxConstants.STATE_LOGO_GRAVITY, logoParams.gravity); + outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_LEFT, logoParams.leftMargin); + outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_TOP, logoParams.topMargin); + outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_RIGHT, logoParams.rightMargin); + outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_BOTTOM, logoParams.bottomMargin); + outState.putInt(MapboxConstants.STATE_LOGO_VISIBILITY, mLogoView.getVisibility()); // Attribution LayoutParams attrParams = (LayoutParams) mAttributionsView.getLayoutParams(); - outState.putInt(STATE_ATTRIBUTION_GRAVITY, attrParams.gravity); - outState.putInt(STATE_ATTRIBUTION_MARGIN_LEFT, attrParams.leftMargin); - outState.putInt(STATE_ATTRIBUTION_MARGIN_TOP, attrParams.topMargin); - outState.putInt(STATE_ATTRIBUTION_MARGIN_RIGHT, attrParams.rightMargin); - outState.putInt(STATE_ATTRIBUTION_MARGIN_BOTTOM, attrParams.bottomMargin); - outState.putInt(STATE_ATTRIBUTION_VISIBILITY, mAttributionsView.getVisibility()); + outState.putInt(MapboxConstants.STATE_ATTRIBUTION_GRAVITY, attrParams.gravity); + outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_LEFT, attrParams.leftMargin); + outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_TOP, attrParams.topMargin); + outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_RIGHT, attrParams.rightMargin); + outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM, attrParams.bottomMargin); + outState.putInt(MapboxConstants.STATE_ATTRIBUTION_VISIBILITY, mAttributionsView.getVisibility()); } /** @@ -1128,243 +495,19 @@ public final class MapView extends FrameLayout { mNativeMapView.onLowMemory(); } - // - // Position - // - - /** - * Returns the current {@link LatLng} at the center of the map view. - * - * @return The current center. - */ - @UiThread - @NonNull - public LatLng getLatLng() { - return mNativeMapView.getLatLng(); - } - - /** - *

- * Centers the map on a new {@link LatLng} immediately without changing the zoom level. - *

- *

- * The initial {@link LatLng} is (0, 0). - *

- * If you want to animate the change, use {@link MapView#setLatLng(LatLng, boolean)}. - * - * @param latLng The new center. - * @see MapView#setLatLng(LatLng, boolean) - */ - @UiThread - public void setLatLng(@NonNull LatLng latLng) { - setLatLng(latLng, false); - } - - /** - *

- * Centers the map on a new {@link LatLng} without changing the zoom level and optionally animates the change. - *

- * The initial {@link LatLng} is (0, 0). - * - * @param latLng The new center. - * @param animated If true, animates the change. If false, immediately changes the map. - */ - @UiThread - public void setLatLng(@NonNull LatLng latLng, boolean animated) { - if (latLng == null) { - Log.w(TAG, "latLng was null, so just returning"); - return; - } - - if (animated) { - CameraPosition cameraPosition = new CameraPosition.Builder(getCameraPosition()) - .target(latLng) - .build(); - animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), - (int) ANIMATION_DURATION, null); - } else { - jumpTo(mNativeMapView.getBearing(), latLng, mNativeMapView.getPitch(), mNativeMapView.getZoom()); - } - } - - - /** - *

- * Centers the map on a new {@link LatLng} immediately while changing the current zoom level. - *

- *

- * The initial value is a center {@link LatLng} of (0, 0) and a zoom level of 0. - *

- * If you want to animate the change, use {@link MapView#setLatLng(LatLng, boolean)}. - * - * @param latLngZoom The new center and zoom level. - * @see MapView#setLatLng(LatLngZoom, boolean) - */ - @UiThread - public void setLatLng(@NonNull LatLngZoom latLngZoom) { - setLatLng(latLngZoom, false); - } - - /** - *

- * Centers the map on a new {@link LatLng} while changing the zoom level and optionally animates the change. - *

- * The initial value is a center {@link LatLng} of (0, 0) and a zoom level of 0. - * - * @param latLngZoom The new center and zoom level. - * @param animated If true, animates the change. If false, immediately changes the map. - */ - @UiThread - public void setLatLng(@NonNull LatLngZoom latLngZoom, boolean animated) { - if (latLngZoom == null) { - Log.w(TAG, "latLngZoom was null, so just returning"); - return; - } - long duration = animated ? ANIMATION_DURATION : 0; - mNativeMapView.cancelTransitions(); - mNativeMapView.setLatLngZoom(latLngZoom, duration); - } - - - /** - * Returns the current coordinate at the center of the map view. - * - * @return The current coordinate. - * @deprecated use {@link #getLatLng()} instead. - */ - @UiThread - @NonNull - @Deprecated - public LatLng getCenterCoordinate() { - return mNativeMapView.getLatLng(); - } - - /** - *

- * Centers the map on a new coordinate immediately without changing the zoom level. - *

- *

- * The initial coordinate is (0, 0). - *

- * If you want to animate the change, use {@link MapView#setCenterCoordinate(LatLng, boolean)}. - * - * @param centerCoordinate The new coordinate. - * @see MapView#setCenterCoordinate(LatLng, boolean) - * @deprecated use {@link #setLatLng(LatLng)}} instead. - */ - @UiThread - @Deprecated - public void setCenterCoordinate(@NonNull LatLng centerCoordinate) { - setCenterCoordinate(centerCoordinate, false); - } - - /** - *

- * Centers the map on a new coordinate without changing the zoom level and optionally animates the change. - *

- * The initial coordinate is (0, 0). - * - * @param centerCoordinate The new coordinate. - * @param animated If true, animates the change. If false, immediately changes the map. - * @deprecated use {@link #setLatLng(LatLng, boolean)}} instead. - */ - @UiThread - @Deprecated - public void setCenterCoordinate(@NonNull LatLng centerCoordinate, boolean animated) { - if (centerCoordinate == null) { - Log.w(TAG, "centerCoordinate was null, so just returning"); - return; - } - - if (animated) { - CameraPosition cameraPosition = new CameraPosition.Builder(getCameraPosition()) - .target(centerCoordinate) - .build(); - animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), - (int) ANIMATION_DURATION, null); - } else { - jumpTo(mNativeMapView.getBearing(), centerCoordinate, mNativeMapView.getPitch(), mNativeMapView.getZoom()); - } - } - - - /** - *

- * Centers the map on a new coordinate immediately while changing the current zoom level. - *

- *

- * The initial value is a center coordinate of (0, 0) and a zoom level of 0. - *

- * If you want to animate the change, use {@link MapView#setCenterCoordinate(LatLngZoom, boolean)}. - * - * @param centerCoordinate The new coordinate and zoom level. - * @see MapView#setCenterCoordinate(LatLngZoom, boolean) - * @deprecated use {@link #setLatLng(LatLngZoom)} instead. - */ - @UiThread - @Deprecated - public void setCenterCoordinate(@NonNull LatLngZoom centerCoordinate) { - setCenterCoordinate(centerCoordinate, false); - } - - /** - *

- * Centers the map on a new coordinate while changing the zoom level and optionally animates the change. - *

- * The initial value is a center coordinate of (0, 0) and a zoom level of 0. - * - * @param centerCoordinate The new coordinate and zoom level. - * @param animated If true, animates the change. If false, immediately changes the map. - * @deprecated use {@link #setLatLng(LatLngZoom, boolean)}} instead. - */ - @UiThread - @Deprecated - public void setCenterCoordinate(@NonNull LatLngZoom centerCoordinate, - boolean animated) { - if (centerCoordinate == null) { - Log.w(TAG, "centerCoordinate was null, so just returning"); - return; - } - long duration = animated ? ANIMATION_DURATION : 0; - mNativeMapView.cancelTransitions(); - mNativeMapView.setLatLngZoom(centerCoordinate, duration); - } - - /** - * Resets the map to the minimum zoom level, a center coordinate of (0, 0), a true north heading, - * and animates the change. - */ - @UiThread - public void resetPosition() { - mNativeMapView.cancelTransitions(); - mNativeMapView.resetPosition(); - } - - /** - * Returns whether the user may scroll around the map. - * - * @return If true, scrolling is enabled. - */ - @UiThread - public boolean isScrollEnabled() { - return mScrollEnabled; - } - - /** - *

- * Changes whether the user may scroll around the map. - *

- *

- * This setting controls only user interactions with the map. If you set the value to false, - * you may still change the map location programmatically. - *

- * The default value is true. - * - * @param scrollEnabled If true, scrolling is enabled. - */ - @UiThread - public void setScrollEnabled(boolean scrollEnabled) { - this.mScrollEnabled = scrollEnabled; + // Called when debug mode is enabled to update a FPS counter + // Called via JNI from NativeMapView + // Forward to any listener + protected void onFpsChanged(final double fps) { + post(new Runnable() { + @Override + public void run() { + MapboxMap.OnFpsChangedListener listener = mMapboxMap.getOnFpsChangedListener(); + if (listener != null) { + listener.onFpsChanged(fps); + } + } + }); } // @@ -1376,7 +519,7 @@ public final class MapView extends FrameLayout { * * @return tilt in degrees */ - public double getTilt() { + double getTilt() { return mNativeMapView.getPitch(); } @@ -1386,8 +529,8 @@ public final class MapView extends FrameLayout { * @param pitch New tilt in degrees * @param duration Animation time in milliseconds. If null then 0 is used, making the animation immediate. */ - @FloatRange(from = MINIMUM_TILT, to = MAXIMUM_TILT) - public void setTilt(Double pitch, @Nullable Long duration) { + @FloatRange(from = MapboxConstants.MINIMUM_TILT, to = MapboxConstants.MAXIMUM_TILT) + void setTilt(Double pitch, @Nullable Long duration) { long actualDuration = 0; if (duration != null) { actualDuration = duration; @@ -1405,8 +548,8 @@ public final class MapView extends FrameLayout { * @return The current heading measured in degrees. */ @UiThread - @FloatRange(from = 0, to = 360) - public double getDirection() { + @FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) + double getDirection() { double direction = -mNativeMapView.getBearing(); while (direction > 360) { @@ -1438,7 +581,7 @@ public final class MapView extends FrameLayout { * @see MapView#setDirection(double, boolean) */ @UiThread - public void setDirection(@FloatRange(from = 0, to = 360) double direction) { + void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction) { setDirection(direction, false); } @@ -1458,8 +601,8 @@ public final class MapView extends FrameLayout { * @param animated If true, animates the change. If false, immediately changes the map. */ @UiThread - public void setDirection(@FloatRange(from = 0, to = 360) double direction, boolean animated) { - long duration = animated ? ANIMATION_DURATION : 0; + void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction, boolean animated) { + long duration = animated ? MapboxConstants.ANIMATION_DURATION : 0; mNativeMapView.cancelTransitions(); // Out of range direactions are normallised in setBearing mNativeMapView.setBearing(-direction, duration); @@ -1469,40 +612,13 @@ public final class MapView extends FrameLayout { * Resets the map heading to true north and animates the change. */ @UiThread - public void resetNorth() { + void resetNorth() { mNativeMapView.cancelTransitions(); mNativeMapView.resetNorth(); } - /** - * Returns whether the user may rotate the map. - * - * @return If true, rotating is enabled. - */ - @UiThread - public boolean isRotateEnabled() { - return mRotateEnabled; - } - - /** - *

- * Changes whether the user may rotate the map. - *

- *

- * This setting controls only user interactions with the map. If you set the value to false, - * you may still change the map location programmatically. - *

- * The default value is true. - * - * @param rotateEnabled If true, rotating is enabled. - */ - @UiThread - public void setRotateEnabled(boolean rotateEnabled) { - this.mRotateEnabled = rotateEnabled; - } - // - // Scale + // Zoom // /** @@ -1511,8 +627,8 @@ public final class MapView extends FrameLayout { * @return The current zoom. */ @UiThread - @FloatRange(from = 0.0, to = MAXIMUM_ZOOM) - public double getZoom() { + @FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) + double getZoom() { return mNativeMapView.getZoom(); } @@ -1526,17 +642,16 @@ public final class MapView extends FrameLayout { * at zoom level 2, tiles cover 1/16 of the world, and so on. *

*

- * The initial zoom level is 0. The maximum zoom level is {@link MapView#MAXIMUM_ZOOM}. + * The initial zoom level is 0. The maximum zoom level is {@link MapboxConstants#MAXIMUM_ZOOM}. *

* If you want to animate the change, use {@link MapView#setZoom(double, boolean)}. * * @param zoomLevel The new zoom. * @see MapView#setZoom(double, boolean) - * @see MapView#MAXIMUM_ZOOM + * @see MapboxConstants#MAXIMUM_ZOOM */ @UiThread - public void setZoom(@FloatRange(from = 0.0, to = MAXIMUM_ZOOM) double zoomLevel) { - setZoom(zoomLevel, false); + void setZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double zoomLevel) { setZoom(zoomLevel, false); } @@ -1549,98 +664,16 @@ public final class MapView extends FrameLayout { * at zoom level 1, tiles cover 1/14 of the world; * at zoom level 2, tiles cover 1/16 of the world, and so on. *

- * The initial zoom level is 0. The maximum zoom level is {@link MapView#MAXIMUM_ZOOM}. + * The initial zoom level is 0. The maximum zoom level is {@link MapboxConstants#MAXIMUM_ZOOM}. * * @param zoomLevel The new zoom level. * @param animated If true, animates the change. If false, immediately changes the map. - * @see MapView#MAXIMUM_ZOOM + * @see MapboxConstants#MAXIMUM_ZOOM */ @UiThread - public void setZoom(@FloatRange(from = 0.0, to = MAXIMUM_ZOOM_LEVEL) double zoomLevel, boolean animated) { - if ((zoomLevel < 0.0) || (zoomLevel > MAXIMUM_ZOOM_LEVEL)) { - throw new IllegalArgumentException("zoomLevel is < 0 or > MapView.MAXIMUM_ZOOM_LEVEL"); - } - long duration = animated ? ANIMATION_DURATION : 0; - mNativeMapView.cancelTransitions(); - mNativeMapView.setZoom(zoomLevel, duration); - } - - /** - * Returns the current zoom level of the map view. - * - * @return The current zoom level. - * @deprecated use {@link #getZoom()} instead. - */ - @UiThread - @FloatRange(from = 0.0, to = MAXIMUM_ZOOM_LEVEL) - @Deprecated - public double getZoomLevel() { - return mNativeMapView.getZoom(); - } - - /** - * Return The current content padding left of the map view viewport. - * @return The current content padding left - */ -/* - public int getContentPaddingLeft() { - return mContentPaddingLeft; - } -*/ - - /** - * Return The current content padding left of the map view viewport. - * @return The current content padding left - */ -/* - public int getContentPaddingTop() { - return mContentPaddingTop; - } -*/ - - /** - * Return The current content padding left of the map view viewport. - * @return The current content padding left - */ -/* - public int getContentPaddingRight() { - return mContentPaddingRight; - } -*/ - - /** - * Return The current content padding left of the map view viewport. - * @return The current content padding left - */ -/* - public int getContentPaddingBottom() { - return mContentPaddingBottom; - } -*/ - - /** - *

- * Zooms the map to a new zoom level immediately without changing the center coordinate. - *

- *

- * At zoom level 0, tiles cover the entire world map; - * at zoom level 1, tiles cover 1/14 of the world; - * at zoom level 2, tiles cover 1/16 of the world, and so on. - *

- *

- * The initial zoom level is 0. The maximum zoom level is {@link MapView#MAXIMUM_ZOOM_LEVEL}. - *

- * If you want to animate the change, use {@link MapView#setZoomLevel(double, boolean)}. - * - * @param zoomLevel The new coordinate. - * @see MapView#setZoomLevel(double, boolean) - * @see MapView#MAXIMUM_ZOOM_LEVEL - * @deprecated use {@link #setZoom(double)} instead. - */ - @UiThread - @Deprecated - public void setZoomLevel(@FloatRange(from = 0.0, to = MAXIMUM_ZOOM_LEVEL) double zoomLevel) { - setZoomLevel(zoomLevel, false); + void setZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double zoomLevel, boolean animated) { + long duration = animated ? MapboxConstants.ANIMATION_DURATION : 0; + setZoom(zoomLevel, duration); } /** @@ -1652,24 +685,97 @@ public final class MapView extends FrameLayout { * at zoom level 1, tiles cover 1/14 of the world; * at zoom level 2, tiles cover 1/16 of the world, and so on. *

- * The initial zoom level is 0. The maximum zoom level is {@link MapView#MAXIMUM_ZOOM_LEVEL}. + * The initial zoom level is 0. The maximum zoom level is {@link MapboxConstants#MAXIMUM_ZOOM}. * - * @param zoomLevel The new coordinate. - * @param animated If true, animates the change. If false, immediately changes the map. - * @see MapView#MAXIMUM_ZOOM_LEVEL - * @deprecated use {@link #setZoom(double, boolean)} instead. + * @param zoomLevel The new zoom level. + * @param duration The length of the animation. + * @see MapboxConstants#MAXIMUM_ZOOM */ @UiThread - @Deprecated - public void setZoomLevel(@FloatRange(from = 0.0, to = MAXIMUM_ZOOM_LEVEL) double zoomLevel, boolean animated) { - if ((zoomLevel < 0.0) || (zoomLevel > MAXIMUM_ZOOM_LEVEL)) { - throw new IllegalArgumentException("zoomLevel is < 0 or > MapView.MAXIMUM_ZOOM_LEVEL"); + void setZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double zoomLevel, long duration) { + if ((zoomLevel < MapboxConstants.MINIMUM_ZOOM) || (zoomLevel > MapboxConstants.MAXIMUM_ZOOM)) { + Log.w(TAG, "Not setting zoom, value is in a unsupported range: " + zoomLevel); + return; } - long duration = animated ? ANIMATION_DURATION : 0; mNativeMapView.cancelTransitions(); mNativeMapView.setZoom(zoomLevel, duration); } + void setZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double zoomLevel, float x, float y) { + if ((zoomLevel < MapboxConstants.MINIMUM_ZOOM) || (zoomLevel > MapboxConstants.MAXIMUM_ZOOM)) { + Log.w(TAG, "Not setting zoom, value is in a unsupported range: " + zoomLevel); + return; + } + LatLng target = fromScreenLocation(new PointF(x, y)); + flyTo(-1, target, MapboxConstants.ANIMATION_DURATION, -1, zoomLevel, null); + } + + void setZoom(CameraUpdateFactory.ZoomUpdate update, long duration) { + switch (update.getType()) { + case CameraUpdateFactory.ZoomUpdate.ZOOM_IN: + setZoom(getZoom() + 1, duration); + break; + case CameraUpdateFactory.ZoomUpdate.ZOOM_OUT: + setZoom(getZoom() - 1, duration); + break; + case CameraUpdateFactory.ZoomUpdate.ZOOM_TO: + setZoom(update.getZoom(), duration); + break; + case CameraUpdateFactory.ZoomUpdate.ZOOM_BY: + setZoom(getZoom() + update.getZoom(), duration); + break; + case CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT: + setZoom(update.getZoom(), update.getX(), update.getY()); + break; + } + } + + +// /** +// * Return The current content padding left of the map view viewport. +// * +// * @return The current content padding left +// */ +///* +// public int getContentPaddingLeft() { +// return mContentPaddingLeft; +// } +//*/ +// +// /** +// * Return The current content padding left of the map view viewport. +// * +// * @return The current content padding left +// */ +///* +// public int getContentPaddingTop() { +// return mContentPaddingTop; +// } +//*/ +// +// /** +// * Return The current content padding left of the map view viewport. +// * +// * @return The current content padding left +// */ +///* +// public int getContentPaddingRight() { +// return mContentPaddingRight; +// } +//*/ +// +// /** +// * Return The current content padding left of the map view viewport. +// * +// * @param zoomLevel The new zoom level. +// * @param animated If true, animates the change. If false, immediately changes the map. +// * @see MapboxMap#MAXIMUM_ZOOM +// */ +///* +// public int getContentPaddingBottom() { +// return mContentPaddingBottom; +//*/ + /** *

* Sets the minimum zoom level the map can be displayed at. @@ -1678,10 +784,7 @@ public final class MapView extends FrameLayout { * @param minZoom The new minimum zoom level. */ @UiThread - public void setMinZoom(@FloatRange(from = 0.0, to = 25.0) double minZoom) { - if ((minZoom < 0.0) || (minZoom > 25.0)) { - throw new IllegalArgumentException("zoomLevel is < 0 or > 25"); - } + void setMinZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) { mNativeMapView.setMinZoom(minZoom); } @@ -1705,10 +808,7 @@ public final class MapView extends FrameLayout { * @param maxZoom The new maximum zoom level. */ @UiThread - public void setMaxZoom(@FloatRange(from = 0.0, to = 25.0) double maxZoom) { - if ((maxZoom < 0.0) || (maxZoom > 25.0)) { - throw new IllegalArgumentException("zoomLevel is < 0 or > 25"); - } + public void setMaxZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) { mNativeMapView.setMaxZoom(maxZoom); } @@ -1724,16 +824,6 @@ public final class MapView extends FrameLayout { return mNativeMapView.getMaxZoom(); } - /** - * Returns whether the user may zoom the map. - * - * @return If true, zooming is enabled. - */ - @UiThread - public boolean isZoomEnabled() { - return mZoomEnabled; - } - /** *

* Changes whether the user may zoom the map. @@ -1747,25 +837,14 @@ public final class MapView extends FrameLayout { * @param zoomEnabled If true, zooming is enabled. */ @UiThread - public void setZoomEnabled(boolean zoomEnabled) { - this.mZoomEnabled = zoomEnabled; - - if (mZoomControlsEnabled && (getVisibility() == View.VISIBLE) && mZoomEnabled) { + void setZoomEnabled(boolean zoomEnabled) { + if (mMapboxMap.isZoomControlsEnabled() && (getVisibility() == View.VISIBLE) && zoomEnabled) { mZoomButtonsController.setVisible(true); } else { mZoomButtonsController.setVisible(false); } } - /** - * Gets whether the zoom controls are enabled. - * - * @return If true, the zoom controls are enabled. - */ - public boolean isZoomControlsEnabled() { - return mZoomControlsEnabled; - } - /** *

* Sets whether the zoom controls are enabled. @@ -1778,10 +857,8 @@ public final class MapView extends FrameLayout { * * @param enabled If true, the zoom controls are enabled. */ - public void setZoomControlsEnabled(boolean enabled) { - mZoomControlsEnabled = enabled; - - if (mZoomControlsEnabled && (getVisibility() == View.VISIBLE) && mZoomEnabled) { + void setZoomControlsEnabled(boolean enabled) { + if (enabled && (getVisibility() == View.VISIBLE) && mMapboxMap.isZoomEnabled()) { mZoomButtonsController.setVisible(true); } else { mZoomButtonsController.setVisible(false); @@ -1798,256 +875,12 @@ public final class MapView extends FrameLayout { mNativeMapView.cancelTransitions(); if (zoomIn) { - mNativeMapView.scaleBy(2.0, x / mScreenDensity, y / mScreenDensity, ANIMATION_DURATION); + mNativeMapView.scaleBy(2.0, x / mScreenDensity, y / mScreenDensity, MapboxConstants.ANIMATION_DURATION); } else { - mNativeMapView.scaleBy(0.5, x / mScreenDensity, y / mScreenDensity, ANIMATION_DURATION); + mNativeMapView.scaleBy(0.5, x / mScreenDensity, y / mScreenDensity, MapboxConstants.ANIMATION_DURATION); } } - // - // Tilt - // - - /** - * Returns whether the user may tilt the map. - * - * @return If true, tilting is enabled. - */ - @UiThread - public boolean isTiltEnabled() { - return mTiltEnabled; - } - - /** - *

- * Changes whether the user may tilt the map. - *

- *

- * This setting controls only user interactions with the map. If you set the value to false, - * you may still change the map location programmatically. - *

- * The default value is true. - * - * @param tiltEnabled If true, tilting is enabled. - */ - @UiThread - public void setTiltEnabled(boolean tiltEnabled) { - this.mTiltEnabled = tiltEnabled; - } - - - // - // Camera API - // - - /** - * Gets the current position of the camera. - * The CameraPosition returned is a snapshot of the current position, and will not automatically update when the camera moves. - * - * @return The current position of the Camera. - */ - public final CameraPosition getCameraPosition() { - return new CameraPosition(getLatLng(), (float) getZoom(), (float) getTilt(), (float) getBearing()); - } - - /** - * Animates the movement of the camera from the current position to the position defined in the update. - * During the animation, a call to getCameraPosition() returns an intermediate location of the camera. - *

- * See CameraUpdateFactory for a set of updates. - * - * @param update The change that should be applied to the camera. - */ - @UiThread - public final void animateCamera(CameraUpdate update) { - animateCamera(update, 1, null); - } - - - /** - * Animates the movement of the camera from the current position to the position defined in the update and calls an optional callback on completion. - * See CameraUpdateFactory for a set of updates. - * During the animation, a call to getCameraPosition() returns an intermediate location of the camera. - * - * @param update The change that should be applied to the camera. - * @param callback The callback to invoke from the main thread when the animation stops. If the animation completes normally, onFinish() is called; otherwise, onCancel() is called. Do not update or animate the camera from within onCancel(). - */ - @UiThread - public final void animateCamera(CameraUpdate update, MapView.CancelableCallback callback) { - animateCamera(update, 1, callback); - } - - /** - * Moves the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates. - * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight. - * - * @param update The change that should be applied to the camera. - * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown. - * @param callback An optional callback to be notified from the main thread when the animation stops. If the animation stops due to its natural completion, the callback will be notified with onFinish(). If the animation stops due to interruption by a later camera movement or a user gesture, onCancel() will be called. The callback should not attempt to move or animate the camera in its cancellation method. If a callback isn't required, leave it as null. - */ - @UiThread - public final void animateCamera(CameraUpdate update, int durationMs, final MapView.CancelableCallback callback) { - - if (update.getTarget() == null) { - Log.w(TAG, "animateCamera with null target coordinate passed in. Will immediately return without animating camera."); - return; - } - - mNativeMapView.cancelTransitions(); - - // Register callbacks early enough - if (callback != null) { - final MapView view = this; - addOnMapChangedListener(new OnMapChangedListener() { - @Override - public void onMapChanged(@MapChange int change) { - if (change == REGION_DID_CHANGE_ANIMATED) { - callback.onFinish(); - - // Clean up after self - removeOnMapChangedListener(this); - } - } - }); - } - - // Convert Degrees To Radians - double angle = -1; - if (update.getBearing() >= 0) { - angle = (-update.getBearing()) * MathConstants.DEG2RAD; - } - double pitch = -1; - if (update.getTilt() >= 0) { - double dp = MathUtils.clamp(update.getTilt(), MINIMUM_TILT, MAXIMUM_TILT); - pitch = dp * MathConstants.DEG2RAD; - } - double zoom = -1; - if (update.getZoom() >= 0) { - zoom = update.getZoom(); - } - - long durationNano = 0; - if (durationMs > 0) { - durationNano = TimeUnit.NANOSECONDS.convert(durationMs, TimeUnit.MILLISECONDS); - } - - flyTo(angle, update.getTarget(), durationNano, pitch, zoom); - } - - /** - * Ease the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates. - * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight. - * - * @param update The change that should be applied to the camera. - * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown. - * @param callback An optional callback to be notified from the main thread when the animation stops. If the animation stops due to its natural completion, the callback will be notified with onFinish(). If the animation stops due to interruption by a later camera movement or a user gesture, onCancel() will be called. The callback should not attempt to move or animate the camera in its cancellation method. If a callback isn't required, leave it as null. - */ - @UiThread - public final void easeCamera(CameraUpdate update, int durationMs, final MapView.CancelableCallback callback) { - if (update.getTarget() == null) { - Log.w(TAG, "easeCamera with null target coordinate passed in. Will immediately return without easing camera."); - return; - } - - mNativeMapView.cancelTransitions(); - - // Register callbacks early enough - if (callback != null) { - final MapView view = this; - addOnMapChangedListener(new OnMapChangedListener() { - @Override - public void onMapChanged(@MapChange int change) { - if (change == REGION_DID_CHANGE_ANIMATED) { - callback.onFinish(); - - // Clean up after self - removeOnMapChangedListener(this); - } - } - }); - } - - // Convert Degrees To Radians - double angle = -1; - if (update.getBearing() >= 0) { - angle = (-update.getBearing()) * MathConstants.DEG2RAD; - } - double pitch = -1; - if (update.getTilt() >= 0) { - double dp = MathUtils.clamp(update.getTilt(), MINIMUM_TILT, MAXIMUM_TILT); - pitch = dp * MathConstants.DEG2RAD; - } - double zoom = -1; - if (update.getZoom() >= 0) { - zoom = update.getZoom(); - } - - long durationNano = 0; - if (durationMs > 0) { - durationNano = TimeUnit.NANOSECONDS.convert(durationMs, TimeUnit.MILLISECONDS); - } - - easeTo(angle, update.getTarget(), durationNano, pitch, zoom); - } - - /** - * Repositions the camera according to the instructions defined in the update. - * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position. - * See CameraUpdateFactory for a set of updates. - * - * @param update The change that should be applied to the camera. - */ - @UiThread - public final void moveCamera(CameraUpdate update) { - if (update.getTarget() == null) { - Log.w(TAG, "moveCamera with null target coordinate passed in. Will immediately return without moving camera."); - return; - } - - mNativeMapView.cancelTransitions(); - - // Convert Degrees To Radians - double angle = -1; - if (update.getBearing() >= 0) { - angle = (-update.getBearing()) * MathConstants.DEG2RAD; - } - double pitch = -1; - if (update.getTilt() >= 0) { - double dp = MathUtils.clamp(update.getTilt(), MINIMUM_TILT, MAXIMUM_TILT); - pitch = dp * MathConstants.DEG2RAD; - } - double zoom = -1; - if (update.getZoom() >= 0) { - zoom = update.getZoom(); - } - - jumpTo(angle, update.getTarget(), pitch, zoom); - } - - // - // InfoWindows - // - - /** - * Changes whether the map allows concurrent multiple infowindows to be shown. - * - * @param allow If true, map allows concurrent multiple infowindows to be shown. - */ - @UiThread - public void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) { - this.mAllowConcurrentMultipleOpenInfoWindows = allow; - } - - /** - * Returns whether the map allows concurrent multiple infowindows to be shown. - * - * @return If true, map allows concurrent multiple infowindows to be shown. - */ - @UiThread - public boolean isAllowConcurrentMultipleOpenInfoWindows() { - return this.mAllowConcurrentMultipleOpenInfoWindows; - } - // // Debug // @@ -2058,7 +891,7 @@ public final class MapView extends FrameLayout { * @return If true, map debug information is currently shown. */ @UiThread - public boolean isDebugActive() { + boolean isDebugActive() { return mNativeMapView.getDebug(); } @@ -2071,7 +904,7 @@ public final class MapView extends FrameLayout { * @param debugActive If true, map debug information is shown. */ @UiThread - public void setDebugActive(boolean debugActive) { + void setDebugActive(boolean debugActive) { mNativeMapView.setDebug(debugActive); } @@ -2085,7 +918,7 @@ public final class MapView extends FrameLayout { * @see MapView#isDebugActive() */ @UiThread - public void cycleDebugOptions() { + void cycleDebugOptions() { mNativeMapView.cycleDebugOptions(); } @@ -2127,180 +960,10 @@ public final class MapView extends FrameLayout { * @see Style */ @UiThread - public void setStyleUrl(@Nullable String url) { - if (url == null) { - url = Style.MAPBOX_STREETS; - } - mStyleUrl = url; + void setStyleUrl(@NonNull String url) { mNativeMapView.setStyleUrl(url); } - /** - *

- * Loads a new map style from the specified bundled style. - *

- *

- * This method is asynchronous and will return immediately before the style finishes loading. - * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event. - *

- * If the style fails to load or an invalid style URL is set, the map view will become blank. - * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be sent. - * - * @param style The bundled style. Accepts one of the values from {@link Style}. - * @see Style - */ - @UiThread - public void setStyle(@Style.StyleUrl String style) { - setStyleUrl(style); - } - - /** - *

- * Returns the map style currently displayed in the map view. - *

- * If the default style is currently displayed, a URL will be returned instead of null. - * - * @return The URL of the map style. - */ - @UiThread - @NonNull - public String getStyleUrl() { - return mStyleUrl; - } - - /** - * Returns the set of currently active map style classes. - * - * @return A list of class identifiers. - */ - @UiThread - @NonNull - public List getStyleClasses() { - return Collections.unmodifiableList(mNativeMapView.getClasses()); - } - - /** - *

- * Changes the set of currently active map style classes immediately. - *

- *

- * The list of valid class identifiers is defined by the currently loaded map style. - *

- * If you want to animate the change, use {@link MapView#setStyleClasses(List, long)}. - * - * @param styleClasses A list of class identifiers. - * @see MapView#setStyleClasses(List, long) - * @see MapView#setStyleUrl(String) - */ - @UiThread - public void setStyleClasses(@NonNull List styleClasses) { - setStyleClasses(styleClasses, 0); - } - - /** - *

- * Changes the set of currently active map style classes with an animated transition. - *

- * The list of valid class identifiers is defined by the currently loaded map style. - * - * @param styleClasses A list of class identifiers. - * @param transitionDuration The duration of the transition animation in milliseconds. - * @see MapView#setStyleClasses(List, long) - * @see MapView#setStyleUrl(String) - */ - @UiThread - public void setStyleClasses(@NonNull List styleClasses, @IntRange(from = 0) long transitionDuration) { - if (styleClasses == null) { - Log.w(TAG, "styleClasses was null, so just returning"); - return; - } - if (transitionDuration < 0) { - throw new IllegalArgumentException("transitionDuration is < 0"); - } - // TODO non negative check and annotation (go back and check other functions too) - mNativeMapView.setDefaultTransitionDuration(transitionDuration); - mNativeMapView.setClasses(styleClasses); - } - - /** - *

- * Activates the specified map style class. - *

- * If you want to animate the change, use {@link MapView#setStyleClasses(List, long)}. - * - * @param styleClass The class identifier. - * @see MapView#setStyleClasses(List, long) - */ - @UiThread - public void addStyleClass(@NonNull String styleClass) { - if (styleClass == null) { - Log.w(TAG, "styleClass was null, so just returning"); - return; - } - mNativeMapView.addClass(styleClass); - } - - /** - *

- * Deactivates the specified map style class. - *

- * If you want to animate the change, use {@link MapView#setStyleClasses(List, long)}. - * - * @param styleClass The class identifier. - * @see MapView#setStyleClasses(List, long) - */ - @UiThread - public void removeStyleClass(@NonNull String styleClass) { - if (styleClass == null) { - Log.w(TAG, "styleClass was null, so just returning"); - return; - } - mNativeMapView.removeClass(styleClass); - } - - /** - * Returns whether the specified map style class is currently active. - * - * @param styleClass The class identifier. - * @return If true, the class is currently active. - */ - @UiThread - public boolean hasStyleClass(@NonNull String styleClass) { - if (styleClass == null) { - Log.w(TAG, "centerCoordinate was null, so just returning false"); - return false; - } - return mNativeMapView.hasClass(styleClass); - } - - /** - *

- * Deactivates all the currently active map style classes immediately. - *

- * If you want to animate the change, use {@link MapView#removeAllStyleClasses(long)}. - * - * @see MapView#removeAllStyleClasses(long) - */ - @UiThread - public void removeAllStyleClasses() { - removeAllStyleClasses(0); - } - - /** - * Deactivates all the currently active map style classes with an animated transition. - * - * @param transitionDuration The duration of the transition animation in milliseconds. - */ - @UiThread - public void removeAllStyleClasses(@IntRange(from = 0) long transitionDuration) { - if (transitionDuration < 0) { - throw new IllegalArgumentException("transitionDuration is < 0"); - } - mNativeMapView.setDefaultTransitionDuration(transitionDuration); - ArrayList styleClasses = new ArrayList<>(0); - setStyleClasses(styleClasses); - } - // // Access token // @@ -2360,12 +1023,7 @@ public final class MapView extends FrameLayout { */ @UiThread @NonNull - public LatLng fromScreenLocation(@NonNull PointF point) { - if (point == null) { - Log.w(TAG, "point was null, so just returning (0, 0)"); - return new LatLng(); - } - + LatLng fromScreenLocation(@NonNull PointF point) { float x = point.x; float y = point.y; @@ -2380,12 +1038,7 @@ public final class MapView extends FrameLayout { */ @UiThread @NonNull - public PointF toScreenLocation(@NonNull LatLng location) { - if (location == null) { - Log.w(TAG, "location was null, so just returning (0, 0)"); - return new PointF(); - } - + PointF toScreenLocation(@NonNull LatLng location) { PointF point = mNativeMapView.pixelForLatLng(location); float x = point.x * mScreenDensity; @@ -2398,10 +1051,6 @@ public final class MapView extends FrameLayout { // Annotations // - public IconFactory getIconFactory() { - return IconFactory.getInstance(getContext()); - } - private void loadIcon(Icon icon) { Bitmap bitmap = icon.getBitmap(); String id = icon.getId(); @@ -2436,7 +1085,7 @@ public final class MapView extends FrameLayout { Marker marker = markerOptions.getMarker(); Icon icon = marker.getIcon(); if (icon == null) { - icon = getIconFactory().defaultMarker(); + icon = IconFactory.getInstance(getContext()).defaultMarker(); marker.setIcon(icon); } if (!mIcons.contains(icon)) { @@ -2464,7 +1113,7 @@ public final class MapView extends FrameLayout { */ @UiThread @NonNull - public Marker addMarker(@NonNull MarkerOptions markerOptions) { + Marker addMarker(@NonNull MarkerOptions markerOptions) { if (markerOptions == null) { Log.w(TAG, "markerOptions was null, so just returning null"); return null; @@ -2473,7 +1122,7 @@ public final class MapView extends FrameLayout { Marker marker = prepareMarker(markerOptions); long id = mNativeMapView.addMarker(marker); marker.setId(id); // the annotation needs to know its id - marker.setMapView(this); // the annotation needs to know which map view it is in + marker.setMapboxMap(mMapboxMap); // the annotation needs to know which map view it is in mAnnotations.add(marker); return marker; } @@ -2490,7 +1139,7 @@ public final class MapView extends FrameLayout { */ @UiThread @NonNull - public List addMarkers(@NonNull List markerOptionsList) { + List addMarkers(@NonNull List markerOptionsList) { if (markerOptionsList == null) { Log.w(TAG, "markerOptionsList was null, so just returning null"); return null; @@ -2510,7 +1159,7 @@ public final class MapView extends FrameLayout { for (int i = 0; i < count; i++) { m = markers.get(i); m.setId(ids[i]); - m.setMapView(this); + m.setMapboxMap(mMapboxMap); mAnnotations.add(m); } @@ -2525,7 +1174,7 @@ public final class MapView extends FrameLayout { */ @UiThread @NonNull - public Polyline addPolyline(@NonNull PolylineOptions polylineOptions) { + Polyline addPolyline(@NonNull PolylineOptions polylineOptions) { if (polylineOptions == null) { Log.w(TAG, "polylineOptions was null, so just returning null"); return null; @@ -2534,7 +1183,7 @@ public final class MapView extends FrameLayout { Polyline polyline = polylineOptions.getPolyline(); long id = mNativeMapView.addPolyline(polyline); polyline.setId(id); - polyline.setMapView(this); + polyline.setMapboxMap(mMapboxMap); mAnnotations.add(polyline); return polyline; } @@ -2547,7 +1196,7 @@ public final class MapView extends FrameLayout { */ @UiThread @NonNull - public List addPolylines(@NonNull List polylineOptionsList) { + List addPolylines(@NonNull List polylineOptionsList) { if (polylineOptionsList == null) { Log.w(TAG, "polylineOptionsList was null, so just returning null"); return null; @@ -2565,7 +1214,7 @@ public final class MapView extends FrameLayout { for (int i = 0; i < count; i++) { p = polylines.get(i); p.setId(ids[i]); - p.setMapView(this); + p.setMapboxMap(mMapboxMap); mAnnotations.add(p); } @@ -2580,7 +1229,7 @@ public final class MapView extends FrameLayout { */ @UiThread @NonNull - public Polygon addPolygon(@NonNull PolygonOptions polygonOptions) { + Polygon addPolygon(@NonNull PolygonOptions polygonOptions) { if (polygonOptions == null) { Log.w(TAG, "polygonOptions was null, so just returning null"); return null; @@ -2589,7 +1238,7 @@ public final class MapView extends FrameLayout { Polygon polygon = polygonOptions.getPolygon(); long id = mNativeMapView.addPolygon(polygon); polygon.setId(id); - polygon.setMapView(this); + polygon.setMapboxMap(mMapboxMap); mAnnotations.add(polygon); return polygon; } @@ -2603,7 +1252,7 @@ public final class MapView extends FrameLayout { */ @UiThread @NonNull - public List addPolygons(@NonNull List polygonOptionsList) { + List addPolygons(@NonNull List polygonOptionsList) { if (polygonOptionsList == null) { Log.w(TAG, "polygonOptionsList was null, so just returning null"); return null; @@ -2621,7 +1270,7 @@ public final class MapView extends FrameLayout { for (int i = 0; i < count; i++) { p = polygons.get(i); p.setId(ids[i]); - p.setMapView(this); + p.setMapboxMap(mMapboxMap); mAnnotations.add(p); } @@ -2638,7 +1287,7 @@ public final class MapView extends FrameLayout { * @param marker Marker to remove */ @UiThread - public void removeMarker(@NonNull Marker marker) { + void removeMarker(@NonNull Marker marker) { removeAnnotation(marker); } @@ -2648,7 +1297,7 @@ public final class MapView extends FrameLayout { * @param annotation The annotation object to remove. */ @UiThread - public void removeAnnotation(@NonNull Annotation annotation) { + void removeAnnotation(@NonNull Annotation annotation) { if (annotation == null) { Log.w(TAG, "annotation was null, so just returning"); return; @@ -2668,7 +1317,7 @@ public final class MapView extends FrameLayout { * @param annotationList A list of annotation objects to remove. */ @UiThread - public void removeAnnotations(@NonNull List annotationList) { + void removeAnnotations(@NonNull List annotationList) { if (annotationList == null) { Log.w(TAG, "annotationList was null, so just returning"); return; @@ -2686,7 +1335,7 @@ public final class MapView extends FrameLayout { * Removes all annotations from the map. */ @UiThread - public void removeAllAnnotations() { + void removeAllAnnotations() { int count = mAnnotations.size(); long[] ids = new long[mAnnotations.size()]; @@ -2710,7 +1359,7 @@ public final class MapView extends FrameLayout { * list will not update the map. */ @NonNull - public List getAllAnnotations() { + List getAllAnnotations() { return new ArrayList<>(mAnnotations); } @@ -2762,90 +1411,10 @@ public final class MapView extends FrameLayout { * @return The distance measured in meters. */ @UiThread - public double getMetersPerPixelAtLatitude(@FloatRange(from = -180, to = 180) double latitude) { + double getMetersPerPixelAtLatitude(@FloatRange(from = -180, to = 180) double latitude) { return mNativeMapView.getMetersPerPixelAtLatitude(latitude, getZoom()) / mScreenDensity; } - /** - *

- * Selects a marker. The selected marker will have it's info window opened. - * Any other open info windows will be closed unless isAllowConcurrentMultipleOpenInfoWindows() - * is true. - *

- * Selecting an already selected marker will have no effect. - * - * @param marker The marker to select. - */ - @UiThread - public void selectMarker(@NonNull Marker marker) { - if (marker == null) { - Log.w(TAG, "marker was null, so just returning"); - return; - } - - if (mSelectedMarkers.contains(marker)) { - return; - } - - // Need to deselect any currently selected annotation first - if (!isAllowConcurrentMultipleOpenInfoWindows()) { - deselectMarkers(); - } - - boolean handledDefaultClick = false; - if (mOnMarkerClickListener != null) { - // end developer has provided a custom click listener - handledDefaultClick = mOnMarkerClickListener.onMarkerClick(marker); - } - - if (!handledDefaultClick) { - if (isInfoWindowValidForMarker(marker)) { - mInfoWindows.add(marker.showInfoWindow(this)); - } - } - - mSelectedMarkers.add(marker); - } - - /** - * Deselects any currently selected marker. All markers will have it's info window closed. - */ - @UiThread - public void deselectMarkers() { - if (mSelectedMarkers.isEmpty()) { - return; - } - - for (Marker marker : mSelectedMarkers) { - if (marker.isInfoWindowShown()) { - marker.hideInfoWindow(); - } - } - - // Removes all selected markers from the list - mSelectedMarkers.clear(); - } - - /** - * Deselects a currently selected marker. The selected marker will have it's info window closed. - */ - @UiThread - public void deselectMarker(@NonNull Marker marker) { - if (!mSelectedMarkers.contains(marker)) { - return; - } - - if (marker.isInfoWindowShown()) { - marker.hideInfoWindow(); - } - - mSelectedMarkers.remove(marker); - } - - private boolean isInfoWindowValidForMarker(@NonNull Marker marker) { - return !TextUtils.isEmpty(marker.getTitle()) || !TextUtils.isEmpty(marker.getSnippet()); - } - // // Mapbox Core GL Camera // @@ -2861,7 +1430,11 @@ public final class MapView extends FrameLayout { * @param zoom Zoom Level */ @UiThread - private void jumpTo(double bearing, LatLng center, double pitch, double zoom) { + void jumpTo(double bearing, LatLng center, double pitch, double zoom) { + if (mNativeMapView == null) { + return; + } + mNativeMapView.cancelTransitions(); mNativeMapView.jumpTo(bearing, center, pitch, zoom); } @@ -2877,7 +1450,27 @@ public final class MapView extends FrameLayout { * @param zoom Zoom Level */ @UiThread - private void easeTo(double bearing, LatLng center, long duration, double pitch, double zoom) { + void easeTo(double bearing, LatLng center, long duration, double pitch, double zoom, @Nullable final MapboxMap.CancelableCallback cancelableCallback) { + if (mNativeMapView == null) { + return; + } + mNativeMapView.cancelTransitions(); + + // Register callbacks early enough + if (cancelableCallback != null) { + addOnMapChangedListener(new OnMapChangedListener() { + @Override + public void onMapChanged(@MapChange int change) { + if (change == REGION_DID_CHANGE_ANIMATED) { + cancelableCallback.onFinish(); + + // Clean up after self + removeOnMapChangedListener(this); + } + } + }); + } + mNativeMapView.easeTo(bearing, center, duration, pitch, zoom); } @@ -2891,7 +1484,27 @@ public final class MapView extends FrameLayout { * @param zoom Zoom Level */ @UiThread - private void flyTo(double bearing, LatLng center, long duration, double pitch, double zoom) { + void flyTo(double bearing, LatLng center, long duration, double pitch, double zoom, @Nullable final MapboxMap.CancelableCallback cancelableCallback) { + if (mNativeMapView == null) { + return; + } + mNativeMapView.cancelTransitions(); + + // Register callbacks early enough + if (cancelableCallback != null) { + addOnMapChangedListener(new OnMapChangedListener() { + @Override + public void onMapChanged(@MapChange int change) { + if (change == REGION_DID_CHANGE_ANIMATED) { + cancelableCallback.onFinish(); + + // Clean up after self + removeOnMapChangedListener(this); + } + } + }); + } + mNativeMapView.flyTo(bearing, center, duration, pitch, zoom); } @@ -2901,7 +1514,7 @@ public final class MapView extends FrameLayout { * @param bounds The bounds that the viewport will show in its entirety. */ @UiThread - public void setVisibleCoordinateBounds(@NonNull CoordinateBounds bounds) { + void setVisibleCoordinateBounds(@NonNull CoordinateBounds bounds) { setVisibleCoordinateBounds(bounds, false); } @@ -2912,7 +1525,7 @@ public final class MapView extends FrameLayout { * @param animated If true, animates the change. If false, immediately changes the map. */ @UiThread - public void setVisibleCoordinateBounds(@NonNull CoordinateBounds bounds, boolean animated) { + void setVisibleCoordinateBounds(@NonNull CoordinateBounds bounds, boolean animated) { setVisibleCoordinateBounds(bounds, new RectF(), animated); } @@ -2925,7 +1538,7 @@ public final class MapView extends FrameLayout { * @param animated If true, animates the change. If false, immediately changes the map. */ @UiThread - public void setVisibleCoordinateBounds(@NonNull CoordinateBounds bounds, @NonNull RectF padding, boolean animated) { + void setVisibleCoordinateBounds(@NonNull CoordinateBounds bounds, @NonNull RectF padding, boolean animated) { LatLng[] coordinates = { new LatLng(bounds.getNorthEast().getLatitude(), bounds.getSouthWest().getLongitude()), bounds.getSouthWest(), @@ -2945,31 +1558,20 @@ public final class MapView extends FrameLayout { * @param animated If true, animates the change. If false, immediately changes the map. */ @UiThread - public void setVisibleCoordinateBounds(@NonNull LatLng[] coordinates, @NonNull RectF padding, boolean animated) { + void setVisibleCoordinateBounds(@NonNull LatLng[] coordinates, @NonNull RectF padding, boolean animated) { setVisibleCoordinateBounds(coordinates, padding, getDirection(), animated); } private void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, boolean animated) { - setVisibleCoordinateBounds(coordinates, padding, direction, animated ? ANIMATION_DURATION : 0l); + setVisibleCoordinateBounds(coordinates, padding, direction, animated ? MapboxConstants.ANIMATION_DURATION : 0l); } - private void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration) { + void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration) { mNativeMapView.setVisibleCoordinateBounds(coordinates, new RectF(padding.left / mScreenDensity, padding.top / mScreenDensity, padding.right / mScreenDensity, padding.bottom / mScreenDensity), direction, duration); } - /** - * Gets the currently selected marker. - * - * @return The currently selected marker. - */ - @UiThread - @Nullable - public List getSelectedMarkers() { - return mSelectedMarkers; - } - private void adjustTopOffsetPixels() { int count = mAnnotations.size(); for (int i = 0; i < count; i++) { @@ -2981,10 +1583,10 @@ public final class MapView extends FrameLayout { } } - for (Marker marker : mSelectedMarkers) { + for (Marker marker : mMapboxMap.getSelectedMarkers()) { if (marker.isInfoWindowShown()) { marker.hideInfoWindow(); - marker.showInfoWindow(this); + marker.showInfoWindow(mMapboxMap, this); } } } @@ -3065,7 +1667,7 @@ public final class MapView extends FrameLayout { public void onSurfaceTextureUpdated(SurfaceTexture surface) { mCompassView.update(getDirection()); mUserLocationView.update(); - for (InfoWindow infoWindow : mInfoWindows) { + for (InfoWindow infoWindow : mMapboxMap.getInfoWindows()) { infoWindow.update(); } } @@ -3083,7 +1685,7 @@ public final class MapView extends FrameLayout { * * @return Bearing in degrees */ - public double getBearing() { + double getBearing() { return mNativeMapView.getBearing(); } @@ -3092,7 +1694,7 @@ public final class MapView extends FrameLayout { * * @param bearing Bearing in degrees */ - public void setBearing(float bearing) { + void setBearing(float bearing) { mNativeMapView.setBearing(bearing); } @@ -3104,7 +1706,7 @@ public final class MapView extends FrameLayout { * @param bearing Bearing in degrees * @param duration Length of time to rotate */ - public void setBearing(float bearing, long duration) { + void setBearing(float bearing, long duration) { mNativeMapView.setBearing(bearing, duration); } @@ -3118,7 +1720,7 @@ public final class MapView extends FrameLayout { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); // Required by ZoomButtonController (from Android SDK documentation) - if (mZoomControlsEnabled) { + if (mMapboxMap.isZoomControlsEnabled()) { mZoomButtonsController.setVisible(false); } } @@ -3127,11 +1729,10 @@ public final class MapView extends FrameLayout { @Override protected void onVisibilityChanged(@NonNull View changedView, int visibility) { // Required by ZoomButtonController (from Android SDK documentation) - if (mZoomControlsEnabled && (visibility != View.VISIBLE)) { + if (mMapboxMap.isZoomControlsEnabled() && (visibility != View.VISIBLE)) { mZoomButtonsController.setVisible(false); } - if (mZoomControlsEnabled && (visibility == View.VISIBLE) - && mZoomEnabled) { + if (mMapboxMap.isZoomControlsEnabled() && (visibility == View.VISIBLE) && mMapboxMap.isZoomEnabled()) { mZoomButtonsController.setVisible(true); } } @@ -3140,29 +1741,6 @@ public final class MapView extends FrameLayout { // Touch events // - /** - *

- * Sets the preference for whether all gestures should be enabled or disabled. - *

- *

- * This setting controls only user interactions with the map. If you set the value to false, - * you may still change the map location programmatically. - *

- * The default value is true. - * - * @param enabled If true, all gestures are available; otherwise, all gestures are disabled. - * @see MapView#setZoomEnabled(boolean) - * @see MapView#setScrollEnabled(boolean) - * @see MapView#setRotateEnabled(boolean) - * @see MapView#setTiltEnabled(boolean) - */ - public void setAllGesturesEnabled(boolean enabled) { - setZoomEnabled(enabled); - setScrollEnabled(enabled); - setRotateEnabled(enabled); - setTiltEnabled(enabled); - } - // Called when user touches the screen, all positions are absolute @Override public boolean onTouchEvent(@NonNull MotionEvent event) { @@ -3228,19 +1806,19 @@ public final class MapView extends FrameLayout { // Must always return true otherwise all events are ignored @Override + @SuppressLint("ResourceType") public boolean onDown(MotionEvent event) { // Show the zoom controls - if (mZoomControlsEnabled && mZoomEnabled) { + if (mMapboxMap.isZoomControlsEnabled() && mMapboxMap.isZoomEnabled()) { mZoomButtonsController.setVisible(true); } - return true; } // Called for double taps @Override public boolean onDoubleTapEvent(MotionEvent e) { - if (!mZoomEnabled) { + if (!mMapboxMap.isZoomEnabled()) { return false; } @@ -3281,6 +1859,8 @@ public final class MapView extends FrameLayout { // Open / Close InfoWindow PointF tapPoint = new PointF(e.getX(), e.getY()); + List selectedMarkers = mMapboxMap.getSelectedMarkers(); + final float toleranceSides = 15 * mScreenDensity; final float toleranceTop = 20 * mScreenDensity; final float toleranceBottom = 5 * mScreenDensity; @@ -3299,21 +1879,20 @@ public final class MapView extends FrameLayout { List nearbyMarkers = getMarkersInBounds(tapBounds); long newSelectedMarkerId = -1; - if (nearbyMarkers!=null && nearbyMarkers.size() > 0) { + if (nearbyMarkers != null && nearbyMarkers.size() > 0) { Collections.sort(nearbyMarkers); for (Marker nearbyMarker : nearbyMarkers) { boolean found = false; - for (Marker selectedMarker : mSelectedMarkers) { - if(selectedMarker.equals(nearbyMarker)){ + for (Marker selectedMarker : selectedMarkers) { + if (selectedMarker.equals(nearbyMarker)) { found = true; } } - if(!found){ + if (!found) { newSelectedMarkerId = nearbyMarker.getId(); break; } } - mMarkersNearLastTap = nearbyMarkers; } if (newSelectedMarkerId >= 0) { @@ -3322,8 +1901,8 @@ public final class MapView extends FrameLayout { Annotation annotation = mAnnotations.get(i); if (annotation instanceof Marker) { if (annotation.getId() == newSelectedMarkerId) { - if (mSelectedMarkers.isEmpty() || !mSelectedMarkers.contains(annotation)) { - selectMarker((Marker) annotation); + if (selectedMarkers.isEmpty() || !selectedMarkers.contains(annotation)) { + mMapboxMap.selectMarker((Marker) annotation); } break; } @@ -3331,12 +1910,13 @@ public final class MapView extends FrameLayout { } } else { // deselect any selected marker - deselectMarkers(); + mMapboxMap.deselectMarkers(); // notify app of map click - if (mOnMapClickListener != null) { + MapboxMap.OnMapClickListener listener = mMapboxMap.getOnMapClickListener(); + if (listener != null) { LatLng point = fromScreenLocation(tapPoint); - mOnMapClickListener.onMapClick(point); + listener.onMapClick(point); } } @@ -3346,9 +1926,10 @@ public final class MapView extends FrameLayout { // Called for a long press @Override public void onLongPress(MotionEvent e) { - if (mOnMapLongClickListener != null && !mQuickZoom) { + MapboxMap.OnMapLongClickListener listener = mMapboxMap.getOnMapLongClickListener(); + if (listener != null && !mQuickZoom) { LatLng point = fromScreenLocation(new PointF(e.getX(), e.getY())); - mOnMapLongClickListener.onMapLongClick(point); + listener.onMapLongClick(point); } } @@ -3356,7 +1937,7 @@ public final class MapView extends FrameLayout { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - if (!mScrollEnabled) { + if (!mMapboxMap.isScrollEnabled()) { return false; } @@ -3378,8 +1959,9 @@ public final class MapView extends FrameLayout { mNativeMapView.moveBy(velocityX * duration / 2.0 / mScreenDensity, velocityY * duration / 2.0 / mScreenDensity, (long) (duration * 1000.0f)); - if (mOnFlingListener != null) { - mOnFlingListener.onFling(); + MapboxMap.OnFlingListener listener = mMapboxMap.getOnFlingListener(); + if (listener != null) { + listener.onFling(); } return true; @@ -3388,7 +1970,7 @@ public final class MapView extends FrameLayout { // Called for drags @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - if (!mScrollEnabled) { + if (!mMapboxMap.isScrollEnabled()) { return false; } @@ -3401,8 +1983,9 @@ public final class MapView extends FrameLayout { // Scroll the map mNativeMapView.moveBy(-distanceX / mScreenDensity, -distanceY / mScreenDensity); - if (mOnScrollListener != null) { - mOnScrollListener.onScroll(); + MapboxMap.OnScrollListener listener = mMapboxMap.getOnScrollListener(); + if (listener != null) { + listener.onScroll(); } return true; @@ -3418,7 +2001,7 @@ public final class MapView extends FrameLayout { // Called when two fingers first touch the screen @Override public boolean onScaleBegin(ScaleGestureDetector detector) { - if (!mZoomEnabled) { + if (!mMapboxMap.isZoomEnabled()) { return false; } @@ -3441,7 +2024,7 @@ public final class MapView extends FrameLayout { // Called for pinch zooms and quickzooms/quickscales @Override public boolean onScale(ScaleGestureDetector detector) { - if (!mZoomEnabled) { + if (!mMapboxMap.isZoomEnabled()) { return false; } @@ -3470,7 +2053,7 @@ public final class MapView extends FrameLayout { mQuickZoom = !mTwoTap; // Scale the map - if (mScrollEnabled && !mQuickZoom && mUserLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE) { + if (mMapboxMap.isScrollEnabled() && !mQuickZoom && mUserLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE) { // around gesture mNativeMapView.scaleBy(detector.getScaleFactor(), detector.getFocusX() / mScreenDensity, detector.getFocusY() / mScreenDensity); } else { @@ -3491,7 +2074,7 @@ public final class MapView extends FrameLayout { // Called when two fingers first touch the screen @Override public boolean onRotateBegin(RotateGestureDetector detector) { - if (!mRotateEnabled) { + if (!mMapboxMap.isRotateEnabled()) { return false; } @@ -3514,7 +2097,7 @@ public final class MapView extends FrameLayout { // Called for rotation @Override public boolean onRotate(RotateGestureDetector detector) { - if (!mRotateEnabled) { + if (!mMapboxMap.isRotateEnabled()) { return false; } @@ -3570,7 +2153,7 @@ public final class MapView extends FrameLayout { @Override public boolean onShoveBegin(ShoveGestureDetector detector) { - if (!mTiltEnabled) { + if (!mMapboxMap.isTiltEnabled()) { return false; } @@ -3590,7 +2173,7 @@ public final class MapView extends FrameLayout { @Override public boolean onShove(ShoveGestureDetector detector) { - if (!mTiltEnabled) { + if (!mMapboxMap.isTiltEnabled()) { return false; } @@ -3619,7 +2202,7 @@ public final class MapView extends FrameLayout { // Get tilt value (scale and clamp) double pitch = getTilt(); pitch -= 0.1 * detector.getShovePixelsDelta(); - pitch = Math.max(MINIMUM_TILT, Math.min(MAXIMUM_TILT, pitch)); + pitch = Math.max(MapboxConstants.MINIMUM_TILT, Math.min(MapboxConstants.MAXIMUM_TILT, pitch)); // Tilt the map setTilt(pitch, null); @@ -3641,7 +2224,7 @@ public final class MapView extends FrameLayout { // Called when user pushes a zoom button @Override public void onZoom(boolean zoomIn) { - if (!mZoomEnabled) { + if (!mMapboxMap.isZoomEnabled()) { return; } @@ -3672,7 +2255,7 @@ public final class MapView extends FrameLayout { return true; case KeyEvent.KEYCODE_DPAD_LEFT: - if (!mScrollEnabled) { + if (!mMapboxMap.isScrollEnabled()) { return false; } @@ -3684,7 +2267,7 @@ public final class MapView extends FrameLayout { return true; case KeyEvent.KEYCODE_DPAD_RIGHT: - if (!mScrollEnabled) { + if (!mMapboxMap.isScrollEnabled()) { return false; } @@ -3696,7 +2279,7 @@ public final class MapView extends FrameLayout { return true; case KeyEvent.KEYCODE_DPAD_UP: - if (!mScrollEnabled) { + if (!mMapboxMap.isScrollEnabled()) { return false; } @@ -3708,7 +2291,7 @@ public final class MapView extends FrameLayout { return true; case KeyEvent.KEYCODE_DPAD_DOWN: - if (!mScrollEnabled) { + if (!mMapboxMap.isScrollEnabled()) { return false; } @@ -3734,7 +2317,7 @@ public final class MapView extends FrameLayout { // onKeyLongPress is fired case KeyEvent.KEYCODE_ENTER: case KeyEvent.KEYCODE_DPAD_CENTER: - if (!mZoomEnabled) { + if (!mMapboxMap.isZoomEnabled()) { return false; } @@ -3764,7 +2347,7 @@ public final class MapView extends FrameLayout { switch (keyCode) { case KeyEvent.KEYCODE_ENTER: case KeyEvent.KEYCODE_DPAD_CENTER: - if (!mZoomEnabled) { + if (!mMapboxMap.isZoomEnabled()) { return false; } @@ -3785,7 +2368,7 @@ public final class MapView extends FrameLayout { switch (event.getActionMasked()) { // The trackball was rotated case MotionEvent.ACTION_MOVE: - if (!mScrollEnabled) { + if (!mMapboxMap.isScrollEnabled()) { return false; } @@ -3813,7 +2396,7 @@ public final class MapView extends FrameLayout { // Trackball was released case MotionEvent.ACTION_UP: - if (!mZoomEnabled) { + if (!mMapboxMap.isZoomEnabled()) { return false; } @@ -3878,7 +2461,7 @@ public final class MapView extends FrameLayout { switch (event.getActionMasked()) { // Mouse scrolls case MotionEvent.ACTION_SCROLL: - if (!mZoomEnabled) { + if (!mMapboxMap.isZoomEnabled()) { return false; } @@ -3911,14 +2494,14 @@ public final class MapView extends FrameLayout { case MotionEvent.ACTION_HOVER_ENTER: case MotionEvent.ACTION_HOVER_MOVE: // Show the zoom controls - if (mZoomControlsEnabled && mZoomEnabled) { + if (mMapboxMap.isZoomControlsEnabled() && mMapboxMap.isZoomEnabled()) { mZoomButtonsController.setVisible(true); } return true; case MotionEvent.ACTION_HOVER_EXIT: // Hide the zoom controls - if (mZoomControlsEnabled) { + if (mMapboxMap.isZoomControlsEnabled()) { mZoomButtonsController.setVisible(false); } @@ -3945,6 +2528,14 @@ public final class MapView extends FrameLayout { } } + // Called when MapView is being created + private boolean isConnected() { + ConnectivityManager connectivityManager = (ConnectivityManager) getContext().getApplicationContext() + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo(); + return (activeNetwork != null) && activeNetwork.isConnectedOrConnecting(); + } + // Called when our Internet connectivity has changed private void onConnectivityChanged(boolean isConnected) { mNativeMapView.setReachability(isConnected); @@ -3995,149 +2586,10 @@ public final class MapView extends FrameLayout { } } - /** - *

- * Sets a custom renderer for the contents of info window. - *

- * When set your callback is invoked when an info window is about to be shown. By returning - * a custom {@link View}, the default info window will be replaced. - * - * @param infoWindowAdapter The callback to be invoked when an info window will be shown. - * To unset the callback, use null. - */ - @UiThread - public void setInfoWindowAdapter(@Nullable InfoWindowAdapter infoWindowAdapter) { - mInfoWindowAdapter = infoWindowAdapter; - } - - /** - * Gets the callback to be invoked when an info window will be shown. - * - * @return The callback to be invoked when an info window will be shown. - */ - @UiThread - @Nullable - public InfoWindowAdapter getInfoWindowAdapter() { - return mInfoWindowAdapter; - } - - - /** - * Sets a callback that's invoked on every frame rendered to the map view. - * - * @param listener The callback that's invoked on every frame rendered to the map view. - * To unset the callback, use null. - */ - @UiThread - public void setOnFpsChangedListener(@Nullable OnFpsChangedListener listener) { - mOnFpsChangedListener = listener; - } - - // Called when debug mode is enabled to update a FPS counter - // Called via JNI from NativeMapView - // Forward to any listener - protected void onFpsChanged(final double fps) { - post(new Runnable() { - @Override - public void run() { - if (mOnFpsChangedListener != null) { - mOnFpsChangedListener.onFpsChanged(fps); - } - } - }); - } - - /** - * Sets a callback that's invoked when the map is scrolled. - * - * @param listener The callback that's invoked when the map is scrolled. - * To unset the callback, use null. - */ - @UiThread - public void setOnScrollListener(@Nullable OnScrollListener listener) { - mOnScrollListener = listener; - } - - /** - * Sets a callback that's invoked when the map is flinged. - * - * @param listener The callback that's invoked when the map is flinged. - * To unset the callback, use null. - */ - @UiThread - public void setOnFlingListener(@Nullable OnFlingListener listener) { - mOnFlingListener = listener; - } - - /** - * Sets a callback that's invoked when the user clicks on the map view. - * - * @param listener The callback that's invoked when the user clicks on the map view. - * To unset the callback, use null. - */ - @UiThread - public void setOnMapClickListener(@Nullable OnMapClickListener listener) { - mOnMapClickListener = listener; - } - - /** - * Sets a callback that's invoked when the user long clicks on the map view. - * - * @param listener The callback that's invoked when the user long clicks on the map view. - * To unset the callback, use null. - */ - @UiThread - public void setOnMapLongClickListener(@Nullable OnMapLongClickListener listener) { - mOnMapLongClickListener = listener; - } - - /** - * Sets a callback that's invoked when the user clicks on a marker. - * - * @param listener The callback that's invoked when the user clicks on a marker. - * To unset the callback, use null. - */ - @UiThread - public void setOnMarkerClickListener(@Nullable OnMarkerClickListener listener) { - mOnMarkerClickListener = listener; - } - - /** - * Sets a callback that's invoked when the user clicks on an info window. - * - * @return The callback that's invoked when the user clicks on an info window. - */ - @UiThread - @Nullable - public OnInfoWindowClickListener getOnInfoWindowClickListener() { - return mOnInfoWindowClickListener; - } - - /** - * Sets a callback that's invoked when the user clicks on an info window. - * - * @param listener The callback that's invoked when the user clicks on an info window. - * To unset the callback, use null. - */ - @UiThread - public void setOnInfoWindowClickListener(@Nullable OnInfoWindowClickListener listener) { - mOnInfoWindowClickListener = listener; - } - // // User location // - /** - * Returns the status of the my-location layer. - * - * @return True if the my-location layer is enabled, false otherwise. - */ - @UiThread - public boolean isMyLocationEnabled() { - return mUserLocationView.isEnabled(); - } - /** *

* Enables or disables the my-location layer. @@ -4155,7 +2607,7 @@ public final class MapView extends FrameLayout { @RequiresPermission(anyOf = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}) - public void setMyLocationEnabled(boolean enabled) { + void setMyLocationEnabled(boolean enabled) { mUserLocationView.setEnabled(enabled); } @@ -4166,7 +2618,7 @@ public final class MapView extends FrameLayout { */ @UiThread @Nullable - public Location getMyLocation() { + Location getMyLocation() { return mUserLocationView.getLocation(); } @@ -4178,7 +2630,7 @@ public final class MapView extends FrameLayout { * To unset the callback, use null. */ @UiThread - public void setOnMyLocationChangeListener(@Nullable OnMyLocationChangeListener listener) { + void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener listener) { mUserLocationView.setOnMyLocationChangeListener(listener); } @@ -4199,16 +2651,16 @@ public final class MapView extends FrameLayout { @RequiresPermission(anyOf = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}) - public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) { - if (myLocationTrackingMode != MyLocationTracking.TRACKING_NONE && !isMyLocationEnabled()) { + void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) { + if (myLocationTrackingMode != MyLocationTracking.TRACKING_NONE && !mMapboxMap.isMyLocationEnabled()) { //noinspection ResourceType - setMyLocationEnabled(true); + mMapboxMap.setMyLocationEnabled(true); } mUserLocationView.setMyLocationTrackingMode(myLocationTrackingMode); - - if (mOnMyLocationTrackingModeChangeListener != null) { - mOnMyLocationTrackingModeChangeListener.onMyLocationTrackingModeChange(myLocationTrackingMode); + MapboxMap.OnMyLocationTrackingModeChangeListener listener = mMapboxMap.getOnMyLocationTrackingModeChangeListener(); + if (listener != null) { + listener.onMyLocationTrackingModeChange(myLocationTrackingMode); } } @@ -4221,21 +2673,10 @@ public final class MapView extends FrameLayout { */ @UiThread @MyLocationTracking.Mode - public int getMyLocationTrackingMode() { + int getMyLocationTrackingMode() { return mUserLocationView.getMyLocationTrackingMode(); } - /** - * Sets a callback that's invoked when the location tracking mode changes. - * - * @param listener The callback that's invoked when the location tracking mode changes. - * To unset the callback, use null. - */ - @UiThread - public void setOnMyLocationTrackingModeChangeListener(@Nullable OnMyLocationTrackingModeChangeListener listener) { - mOnMyLocationTrackingModeChangeListener = listener; - } - /** *

* Set the current my bearing tracking mode. @@ -4255,16 +2696,15 @@ public final class MapView extends FrameLayout { @RequiresPermission(anyOf = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}) - public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) { - if (myBearingTrackingMode != MyBearingTracking.NONE && !isMyLocationEnabled()) { + void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) { + if (myBearingTrackingMode != MyBearingTracking.NONE && !mMapboxMap.isMyLocationEnabled()) { //noinspection ResourceType - setMyLocationEnabled(true); + mMapboxMap.setMyLocationEnabled(true); } - mUserLocationView.setMyBearingTrackingMode(myBearingTrackingMode); - - if (mOnMyBearingTrackingModeChangeListener != null) { - mOnMyBearingTrackingModeChangeListener.onMyBearingTrackingModeChange(myBearingTrackingMode); + MapboxMap.OnMyBearingTrackingModeChangeListener listener = mMapboxMap.getOnMyBearingTrackingModeChangeListener(); + if (listener != null) { + listener.onMyBearingTrackingModeChange(myBearingTrackingMode); } } @@ -4277,23 +2717,12 @@ public final class MapView extends FrameLayout { */ @UiThread @MyLocationTracking.Mode - public int getMyBearingTrackingMode() { + int getMyBearingTrackingMode() { //noinspection ResourceType return mUserLocationView.getMyBearingTrackingMode(); } - /** - * Sets a callback that's invoked when the bearing tracking mode changes. - * - * @param listener The callback that's invoked when the bearing tracking mode changes. - * To unset the callback, use null. - */ - @UiThread - public void setOnMyBearingTrackingModeChangeListener(@Nullable OnMyBearingTrackingModeChangeListener listener) { - mOnMyBearingTrackingModeChangeListener = listener; - } - - private void resetTrackingModes(){ + private void resetTrackingModes() { try { //noinspection ResourceType setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE); @@ -4314,7 +2743,7 @@ public final class MapView extends FrameLayout { * @return True if the compass is enabled; false if the compass is disabled. */ @UiThread - public boolean isCompassEnabled() { + boolean isCompassEnabled() { return mCompassView.isEnabled(); } @@ -4330,7 +2759,7 @@ public final class MapView extends FrameLayout { * @param compassEnabled True to enable the compass; false to disable the compass. */ @UiThread - public void setCompassEnabled(boolean compassEnabled) { + void setCompassEnabled(boolean compassEnabled) { mCompassView.setEnabled(compassEnabled); } @@ -4345,7 +2774,7 @@ public final class MapView extends FrameLayout { * @see Gravity */ @UiThread - public void setCompassGravity(int gravity) { + void setCompassGravity(int gravity) { setWidgetGravity(mCompassView, gravity); } @@ -4359,7 +2788,7 @@ public final class MapView extends FrameLayout { * @param bottom The bottom margin in pixels. */ @UiThread - public void setCompassMargins(int left, int top, int right, int bottom) { + void setCompassMargins(int left, int top, int right, int bottom) { setWidgetMargins(mCompassView, left, top, right, bottom); } @@ -4378,7 +2807,7 @@ public final class MapView extends FrameLayout { * @see Gravity */ @UiThread - public void setLogoGravity(int gravity) { + void setLogoGravity(int gravity) { setWidgetGravity(mLogoView, gravity); } @@ -4392,7 +2821,7 @@ public final class MapView extends FrameLayout { * @param bottom The bottom margin in pixels. */ @UiThread - public void setLogoMargins(int left, int top, int right, int bottom) { + void setLogoMargins(int left, int top, int right, int bottom) { setWidgetMargins(mLogoView, left, top, right, bottom); } @@ -4405,7 +2834,7 @@ public final class MapView extends FrameLayout { * @param visibility True to enable the logo; false to disable the logo. */ @UiThread - public void setLogoVisibility(int visibility) { + void setLogoVisibility(int visibility) { mLogoView.setVisibility(visibility); } @@ -4424,7 +2853,7 @@ public final class MapView extends FrameLayout { * @see Gravity */ @UiThread - public void setAttributionGravity(int gravity) { + void setAttributionGravity(int gravity) { setWidgetGravity(mAttributionsView, gravity); } @@ -4438,42 +2867,44 @@ public final class MapView extends FrameLayout { * @param bottom The bottom margin in pixels. */ @UiThread - public void setAttributionMargins(int left, int top, int right, int bottom) { + void setAttributionMargins(int left, int top, int right, int bottom) { setWidgetMargins(mAttributionsView, left, top, right, bottom); } + // + // Content padding + // - /** - * Sets the distance from the edges of the map view’s frame to the edges of the map - * view’s logical viewport. - * - * When the value of this property is equal to {0,0,0,0}, viewport - * properties such as `getLatLng` assume a viewport that matches the map - * view’s frame. Otherwise, those properties are inset, excluding part of the - * frame from the viewport. For instance, if the only the top edge is inset, the - * map center is effectively shifted downward. - * - * @param left The left margin in pixels. - * @param top The top margin in pixels. - * @param right The right margin in pixels. - * @param bottom The bottom margin in pixels. - */ -/* - @UiThread - public void setContentPadding(int left, int top, int right, int bottom) { - - if (left == mContentPaddingLeft && top == mContentPaddingTop && right == mContentPaddingRight && bottom == mContentPaddingBottom) { - return; - } - - mContentPaddingLeft = left; - mContentPaddingTop = top; - mContentPaddingRight = right; - mContentPaddingBottom = bottom; - - mNativeMapView.setContentPadding(top / mScreenDensity, left / mScreenDensity, bottom / mScreenDensity, right / mScreenDensity); - } -*/ +// /** +// * Sets the distance from the edges of the map view’s frame to the edges of the map +// * view’s logical viewport. +// *

+// * When the value of this property is equal to {0,0,0,0}, viewport +// * properties such as `getLatLng` assume a viewport that matches the map +// * view’s frame. Otherwise, those properties are inset, excluding part of the +// * frame from the viewport. For instance, if the only the top edge is inset, the +// * map center is effectively shifted downward. +// * +// * @param left The left margin in pixels. +// * @param top The top margin in pixels. +// * @param right The right margin in pixels. +// * @param bottom The bottom margin in pixels. +// */ +// +// @UiThread +// void setContentPadding(int left, int top, int right, int bottom) { +// +// if (left == mContentPaddingLeft && top == mContentPaddingTop && right == mContentPaddingRight && bottom == mContentPaddingBottom) { +// return; +// } +// +// mContentPaddingLeft = left; +// mContentPaddingTop = top; +// mContentPaddingRight = right; +// mContentPaddingBottom = bottom; +// +// mNativeMapView.setContentPadding(top / mScreenDensity, left / mScreenDensity, bottom / mScreenDensity, right / mScreenDensity); +// } /** *

@@ -4486,25 +2917,51 @@ public final class MapView extends FrameLayout { * @param visibility True to enable the attribution button; false to disable the attribution button. */ @UiThread - public void setAttributionVisibility(int visibility) { + void setAttributionVisibility(int visibility) { mAttributionsView.setVisibility(visibility); } + // + // Custom layer + // + @UiThread - public void addCustomLayer(CustomLayer customLayer, String before) { + void addCustomLayer(CustomLayer customLayer, String before) { mNativeMapView.addCustomLayer(customLayer, before); } @UiThread - public void removeCustomLayer(String id) { + void removeCustomLayer(String id) { mNativeMapView.removeCustomLayer(id); } @UiThread - public void invalidateCustomLayers() { + void invalidateCustomLayers() { mNativeMapView.update(); } + /** + * Sets a callback object which will be triggered when the {@link MapboxMap} instance is ready to be used. + * + * @param callback The callback object that will be triggered when the map is ready to be used. + */ + @UiThread + public void getMapAsync(@NonNull OnMapReadyCallback callback) { + callback.onMapReady(mMapboxMap); + } + + MapboxMap getMapboxMap() { + return mMapboxMap; + } + + void setMapboxMap(MapboxMap mapboxMap) { + mMapboxMap = mapboxMap; + } + + // + // View utility methods + // + private void setWidgetGravity(@NonNull final View view, int gravity) { LayoutParams layoutParams = (LayoutParams) view.getLayoutParams(); layoutParams.gravity = gravity; @@ -4525,6 +2982,7 @@ public final class MapView extends FrameLayout { private static class AttributionOnClickListener implements View.OnClickListener, DialogInterface.OnClickListener { + private static final int ATTRIBUTION_INDEX_IMPROVE_THIS_MAP = 2; private MapView mMapView; public AttributionOnClickListener(MapView mapView) { @@ -4548,7 +3006,7 @@ public final class MapView extends FrameLayout { Context context = ((Dialog) dialog).getContext(); String url = context.getResources().getStringArray(R.array.attribution_links)[which]; if (which == ATTRIBUTION_INDEX_IMPROVE_THIS_MAP) { - LatLng latLng = mMapView.getLatLng(); + LatLng latLng = mMapView.getMapboxMap().getCameraPosition().target; url = String.format(url, latLng.getLongitude(), latLng.getLatitude(), (int) mMapView.getZoom()); } Intent intent = new Intent(Intent.ACTION_VIEW); @@ -4556,4 +3014,204 @@ public final class MapView extends FrameLayout { context.startActivity(intent); } } + + + /** + * Map change event types. + * + * @see MapView.OnMapChangedListener#onMapChanged(int) + */ + @IntDef({REGION_WILL_CHANGE, + REGION_WILL_CHANGE_ANIMATED, + REGION_IS_CHANGING, + REGION_DID_CHANGE, + REGION_DID_CHANGE_ANIMATED, + WILL_START_LOADING_MAP, + DID_FINISH_LOADING_MAP, + DID_FAIL_LOADING_MAP, + WILL_START_RENDERING_FRAME, + DID_FINISH_RENDERING_FRAME, + DID_FINISH_RENDERING_FRAME_FULLY_RENDERED, + WILL_START_RENDERING_MAP, + DID_FINISH_RENDERING_MAP, + DID_FINISH_RENDERING_MAP_FULLY_RENDERED + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MapChange { + } + + /** + *

+ * This {@link MapChange} is triggered whenever the currently displayed map region is about to changing + * without an animation. + *

+ *

+ * This event is followed by a series of {@link MapView#REGION_IS_CHANGING} and ends + * with {@link MapView#REGION_DID_CHANGE}. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int REGION_WILL_CHANGE = 0; + + /** + *

+ * This {@link MapChange} is triggered whenever the currently displayed map region is about to changing + * with an animation. + *

+ *

+ * This event is followed by a series of {@link MapView#REGION_IS_CHANGING} and ends + * with {@link MapView#REGION_DID_CHANGE_ANIMATED}. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int REGION_WILL_CHANGE_ANIMATED = 1; + + /** + *

+ * This {@link MapChange} is triggered whenever the currently displayed map region is changing. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int REGION_IS_CHANGING = 2; + + /** + *

+ * This {@link MapChange} is triggered whenever the currently displayed map region finished changing + * without an animation. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int REGION_DID_CHANGE = 3; + + /** + *

+ * This {@link MapChange} is triggered whenever the currently displayed map region finished changing + * with an animation. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int REGION_DID_CHANGE_ANIMATED = 4; + + /** + *

+ * This {@link MapChange} is triggered when the map is about to start loading a new map style. + *

+ *

+ * This event is followed by {@link MapView#DID_FINISH_LOADING_MAP} or + * {@link MapView#DID_FAIL_LOADING_MAP}. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int WILL_START_LOADING_MAP = 5; + + /** + *

+ * This {@link MapChange} is triggered when the map has successfully loaded a new map style. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_LOADING_MAP = 6; + + /** + *

+ * This {@link MapChange} is currently not implemented. + *

+ *

+ * This event is triggered when the map has failed to load a new map style. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int DID_FAIL_LOADING_MAP = 7; + + /** + *

+ * This {@link MapChange} is currently not implemented. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int WILL_START_RENDERING_FRAME = 8; + + /** + *

+ * This {@link MapChange} is currently not implemented. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_RENDERING_FRAME = 9; + + /** + *

+ * This {@link MapChange} is currently not implemented. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_RENDERING_FRAME_FULLY_RENDERED = 10; + + /** + *

+ * This {@link MapChange} is currently not implemented. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int WILL_START_RENDERING_MAP = 11; + + /** + *

+ * This {@link MapChange} is currently not implemented. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_RENDERING_MAP = 12; + + /** + *

+ * This {@link MapChange} is currently not implemented. + *

+ * + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_RENDERING_MAP_FULLY_RENDERED = 13; + + + /** + * Interface definition for a callback to be invoked when the displayed map view changes. + * + * @see MapView#addOnMapChangedListener(OnMapChangedListener) + * @see MapView.MapChange + */ + public interface OnMapChangedListener { + /** + * Called when the displayed map view changes. + * + * @param change Type of map change event, one of {@link #REGION_WILL_CHANGE}, + * {@link #REGION_WILL_CHANGE_ANIMATED}, + * {@link #REGION_IS_CHANGING}, + * {@link #REGION_DID_CHANGE}, + * {@link #REGION_DID_CHANGE_ANIMATED}, + * {@link #WILL_START_LOADING_MAP}, + * {@link #DID_FAIL_LOADING_MAP}, + * {@link #DID_FINISH_LOADING_MAP}, + * {@link #WILL_START_RENDERING_FRAME}, + * {@link #DID_FINISH_RENDERING_FRAME}, + * {@link #DID_FINISH_RENDERING_FRAME_FULLY_RENDERED}, + * {@link #WILL_START_RENDERING_MAP}, + * {@link #DID_FINISH_RENDERING_MAP}, + * {@link #DID_FINISH_RENDERING_MAP_FULLY_RENDERED}. + */ + void onMapChanged(@MapChange int change); + } + } 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 new file mode 100644 index 000000000..843386dd0 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java @@ -0,0 +1,1557 @@ +package com.mapbox.mapboxsdk.maps; + +import android.Manifest; +import android.content.Context; +import android.graphics.PointF; +import android.location.Location; +import android.os.Bundle; +import android.support.annotation.FloatRange; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresPermission; +import android.support.annotation.UiThread; +import android.text.TextUtils; +import android.util.Log; +import android.view.Gravity; +import android.view.View; + +import com.mapbox.mapboxsdk.annotations.Annotation; +import com.mapbox.mapboxsdk.annotations.InfoWindow; +import com.mapbox.mapboxsdk.annotations.Marker; +import com.mapbox.mapboxsdk.annotations.MarkerOptions; +import com.mapbox.mapboxsdk.annotations.Polygon; +import com.mapbox.mapboxsdk.annotations.PolygonOptions; +import com.mapbox.mapboxsdk.annotations.Polyline; +import com.mapbox.mapboxsdk.annotations.PolylineOptions; +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.camera.CameraUpdate; +import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; +import com.mapbox.mapboxsdk.constants.MapboxConstants; +import com.mapbox.mapboxsdk.constants.MyBearingTracking; +import com.mapbox.mapboxsdk.constants.MyLocationTracking; +import com.mapbox.mapboxsdk.constants.Style; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.layers.CustomLayer; +import com.mapbox.mapboxsdk.utils.ApiAccess; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class MapboxMap { + + private MapView mMapView; + private CameraPosition mCurrentCameraPosition; + private String mStyleUrl; + private List mSelectedMarkers; + private List mInfoWindows; + private MapboxMap.InfoWindowAdapter mInfoWindowAdapter; + + private boolean mZoomEnabled = true; + private boolean mScrollEnabled = true; + private boolean mRotateEnabled = true; + private boolean mTiltEnabled = true; + private boolean mCompassEnabled = true; + private boolean mMyLocationEnabled; + private boolean mAllowConcurrentMultipleInfoWindows; + private boolean mZoomControlsEnabled; + + private MapboxMap.OnMapClickListener mOnMapClickListener; + private MapboxMap.OnMapLongClickListener mOnMapLongClickListener; + private MapboxMap.OnMarkerClickListener mOnMarkerClickListener; + private MapboxMap.OnInfoWindowClickListener mOnInfoWindowClickListener; + private MapboxMap.OnFlingListener mOnFlingListener; + private MapboxMap.OnScrollListener mOnScrollListener; + private MapboxMap.OnMyLocationTrackingModeChangeListener mOnMyLocationTrackingModeChangeListener; + private MapboxMap.OnMyBearingTrackingModeChangeListener mOnMyBearingTrackingModeChangeListener; + private MapboxMap.OnFpsChangedListener mOnFpsChangedListener; + + MapboxMap(@NonNull MapView mapView) { + mMapView = mapView; + mSelectedMarkers = new ArrayList<>(); + mInfoWindows = new ArrayList<>(); + } + + // + // Camera API + // + + /** + * Gets the current position of the camera. + * The CameraPosition returned is a snapshot of the current position, and will not automatically update when the camera moves. + * + * @return The current position of the Camera. + */ + public final CameraPosition getCameraPosition() { + return mCurrentCameraPosition; + } + + /** + * Repositions the camera according to the cameraPosition. + * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position. + * See CameraUpdateFactory for a set of updates. + * + * @param cameraPosition + */ + public void setCameraPosition(@NonNull CameraPosition cameraPosition) { + moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition)); + } + + /** + * Repositions the camera according to the instructions defined in the update. + * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position. + * See CameraUpdateFactory for a set of updates. + * + * @param update The change that should be applied to the camera. + */ + @UiThread + public final void moveCamera(CameraUpdate update) { + if (update instanceof CameraUpdateFactory.PositionCameraUpdate) { + CameraUpdateFactory.PositionCameraUpdate positionCameraUpdate = (CameraUpdateFactory.PositionCameraUpdate) update; + CameraPosition cameraPosition = new CameraPosition.Builder(positionCameraUpdate).build(); + updateCameraPosition(cameraPosition); + mMapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom); + }else if (update instanceof CameraUpdateFactory.ZoomUpdate) { + mMapView.setZoom((CameraUpdateFactory.ZoomUpdate) update, 0); + } + } + + /** + * Ease the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates. + * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown. + */ + @UiThread + public final void easeCamera(CameraUpdate update, int durationMs) { + easeCamera(update, durationMs, null); + } + + /** + * Ease the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates. + * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown. + * @param callback An optional callback to be notified from the main thread when the animation stops. If the animation stops due to its natural completion, the callback will be notified with onFinish(). If the animation stops due to interruption by a later camera movement or a user gesture, onCancel() will be called. The callback should not attempt to move or animate the camera in its cancellation method. If a callback isn't required, leave it as null. + */ + @UiThread + public final void easeCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) { + if (update instanceof CameraUpdateFactory.PositionCameraUpdate) { + CameraUpdateFactory.PositionCameraUpdate positionCameraUpdate = (CameraUpdateFactory.PositionCameraUpdate) update; + CameraPosition cameraPosition = new CameraPosition.Builder(positionCameraUpdate).build(); + updateCameraPosition(cameraPosition); + mMapView.easeTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt, cameraPosition.zoom, callback); + }else if (update instanceof CameraUpdateFactory.ZoomUpdate) { + mMapView.setZoom((CameraUpdateFactory.ZoomUpdate) update, durationMs); + } + } + + /** + * Animates the movement of the camera from the current position to the position defined in the update. + * During the animation, a call to getCameraPosition() returns an intermediate location of the camera. + *

+ * See CameraUpdateFactory for a set of updates. + * + * @param update The change that should be applied to the camera. + */ + @UiThread + public final void animateCamera(CameraUpdate update) { + animateCamera(update, MapboxConstants.ANIMATION_DURATION, null); + } + + /** + * Animates the movement of the camera from the current position to the position defined in the update and calls an optional callback on completion. + * See CameraUpdateFactory for a set of updates. + * During the animation, a call to getCameraPosition() returns an intermediate location of the camera. + * + * @param update The change that should be applied to the camera. + * @param callback The callback to invoke from the main thread when the animation stops. If the animation completes normally, onFinish() is called; otherwise, onCancel() is called. Do not update or animate the camera from within onCancel(). + */ + @UiThread + public final void animateCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) { + animateCamera(update, MapboxConstants.ANIMATION_DURATION, callback); + } + + /** + * Moves the map according to the update with an animation over a specified duration. See CameraUpdateFactory for a set of updates. + * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown. + */ + @UiThread + public final void animateCamera(CameraUpdate update, int durationMs) { + animateCamera(update, durationMs, null); + } + + /** + * Moves the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates. + * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown. + * @param callback An optional callback to be notified from the main thread when the animation stops. If the animation stops due to its natural completion, the callback will be notified with onFinish(). If the animation stops due to interruption by a later camera movement or a user gesture, onCancel() will be called. The callback should not attempt to move or animate the camera in its cancellation method. If a callback isn't required, leave it as null. + */ + @UiThread + public final void animateCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) { + if (update instanceof CameraUpdateFactory.PositionCameraUpdate) { + CameraUpdateFactory.PositionCameraUpdate positionCameraUpdate = (CameraUpdateFactory.PositionCameraUpdate) update; + CameraPosition cameraPosition = new CameraPosition.Builder(positionCameraUpdate).build(); + updateCameraPosition(cameraPosition); + mMapView.flyTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt, cameraPosition.zoom, callback); + } else if (update instanceof CameraUpdateFactory.ZoomUpdate) { + mMapView.setZoom((CameraUpdateFactory.ZoomUpdate) update, durationMs); + } + } + + // internal setter for CameraPosition + void updateCameraPosition(@NonNull CameraPosition cameraPosition) { + mCurrentCameraPosition = cameraPosition; + } + + // internal time layer conversion + private long getDurationNano(long durationMs) { + return durationMs > 0 ? TimeUnit.NANOSECONDS.convert(durationMs, TimeUnit.MILLISECONDS) : 0; + } + + // + // Scroll + // + + /** + * Returns whether the user may scroll around the map. + * + * @return If true, scrolling is enabled. + */ + @UiThread + public boolean isScrollEnabled() { + return mScrollEnabled; + } + + /** + *

+ * Changes whether the user may scroll around the map. + *

+ *

+ * This setting controls only user interactions with the map. If you set the value to false, + * you may still change the map location programmatically. + *

+ * The default value is true. + * + * @param scrollEnabled If true, scrolling is enabled. + */ + @UiThread + public void setScrollEnabled(boolean scrollEnabled) { + mScrollEnabled = scrollEnabled; + } + + // + // Rotation + // + + /** + * Returns whether the user may rotate the map. + * + * @return If true, rotating is enabled. + */ + @UiThread + public boolean isRotateEnabled() { + return mRotateEnabled; + } + + /** + *

+ * Changes whether the user may rotate the map. + *

+ *

+ * This setting controls only user interactions with the map. If you set the value to false, + * you may still change the map location programmatically. + *

+ * The default value is true. + * + * @param rotateEnabled If true, rotating is enabled. + */ + @UiThread + public void setRotateEnabled(boolean rotateEnabled) { + mRotateEnabled = rotateEnabled; + } + + // + // ZOOM + // + + /** + * Returns whether the user may zoom the map. + * + * @return If true, zooming is enabled. + */ + @UiThread + public boolean isZoomEnabled() { + return mZoomEnabled; + } + + /** + *

+ * Changes whether the user may zoom the map. + *

+ *

+ * This setting controls only user interactions with the map. If you set the value to false, + * you may still change the map location programmatically. + *

+ * The default value is true. + * + * @param zoomEnabled If true, zooming is enabled. + */ + @UiThread + public void setZoomEnabled(boolean zoomEnabled) { + mZoomEnabled = zoomEnabled; + mMapView.setZoomEnabled(true); + } + + /** + *

+ * Sets the minimum zoom level the map can be displayed at. + *

+ * + * @param minZoom The new minimum zoom level. + */ + @UiThread + public void setMinZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) { + if ((minZoom < MapboxConstants.MINIMUM_ZOOM) || (minZoom > MapboxConstants.MAXIMUM_ZOOM)) { + Log.e(MapboxConstants.TAG, "Not setting minZoom, value is in unsupported range: " + minZoom); + return; + } + mMapView.setMinZoom(minZoom); + } + + /** + *

+ * Gets the maximum zoom level the map can be displayed at. + *

+ * + * @return The minimum zoom level. + */ + @UiThread + public double getMinZoom() { + return mMapView.getMinZoom(); + } + + /** + *

+ * Sets the maximum zoom level the map can be displayed at. + *

+ * + * @param maxZoom The new maximum zoom level. + */ + @UiThread + public void setMaxZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) { + if ((maxZoom < MapboxConstants.MINIMUM_ZOOM) || (maxZoom > MapboxConstants.MAXIMUM_ZOOM)) { + Log.e(MapboxConstants.TAG, "Not setting maxZoom, value is in unsupported range: " + maxZoom); + return; + } + mMapView.setMaxZoom(maxZoom); + } + + /** + *

+ * Gets the maximum zoom level the map can be displayed at. + *

+ * + * @return The maximum zoom level. + */ + @UiThread + public double getMaxZoom() { + return mMapView.getMaxZoom(); + } + + // + // Manual zoom controls + // + + /** + * Gets whether the zoom controls are enabled. + * + * @return If true, the zoom controls are enabled. + */ + public boolean isZoomControlsEnabled() { + return mZoomControlsEnabled; + } + + /** + *

+ * Sets whether the zoom controls are enabled. + * If enabled, the zoom controls are a pair of buttons + * (one for zooming in, one for zooming out) that appear on the screen. + * When pressed, they cause the camera to zoom in (or out) by one zoom level. + * If disabled, the zoom controls are not shown. + *

+ * By default the zoom controls are enabled if the device is only single touch capable; + * + * @param enabled If true, the zoom controls are enabled. + */ + public void setZoomControlsEnabled(boolean enabled) { + mZoomControlsEnabled = enabled; + mMapView.setZoomControlsEnabled(enabled); + } + + // + // Tilt + // + + /** + * Returns whether the user may tilt the map. + * + * @return If true, tilting is enabled. + */ + @UiThread + public boolean isTiltEnabled() { + return mTiltEnabled; + } + + /** + *

+ * Changes whether the user may tilt the map. + *

+ *

+ * This setting controls only user interactions with the map. If you set the value to false, + * you may still change the map location programmatically. + *

+ * The default value is true. + * + * @param tiltEnabled If true, tilting is enabled. + */ + @UiThread + public void setTiltEnabled(boolean tiltEnabled) { + mTiltEnabled = tiltEnabled; + } + + // + // Debug + // + + /** + * Returns whether the map debug information is currently shown. + * + * @return If true, map debug information is currently shown. + */ + @UiThread + public boolean isDebugActive() { + return mMapView.isDebugActive(); + } + + /** + *

+ * Changes whether the map debug information is shown. + *

+ * The default value is false. + * + * @param debugActive If true, map debug information is shown. + */ + @UiThread + public void setDebugActive(boolean debugActive) { + mMapView.setDebugActive(debugActive); + } + + /** + *

+ * Cycles through the map debug options. + *

+ * The value of {@link MapView#isDebugActive()} reflects whether there are + * any map debug options enabled or disabled. + * + * @see MapView#isDebugActive() + */ + @UiThread + public void cycleDebugOptions() { + mMapView.cycleDebugOptions(); + } + + // + // Styling + // + + /** + *

+ * Loads a new map style from the specified URL. + *

+ * {@code url} can take the following forms: + *
    + *
  • {@code Style.*}: load one of the bundled styles in {@link Style}.
  • + *
  • {@code mapbox://styles//