summaryrefslogtreecommitdiff
path: root/platform/android
diff options
context:
space:
mode:
authorTobrun <tobrun.van.nuland@gmail.com>2016-11-07 17:23:51 +0100
committerGitHub <noreply@github.com>2016-11-07 17:23:51 +0100
commit1f8f85fab32f583101cc6cccee8a5463aba6dab7 (patch)
tree168d0d6c20413b63c9695457bd0a942b164aeba6 /platform/android
parent5412191ab484cc82f2864fd9cf360939c823fc33 (diff)
downloadqtlocation-mapboxgl-1f8f85fab32f583101cc6cccee8a5463aba6dab7.tar.gz
6067 annotation manager (#6913)
* [android] - AnnotationManager and InfoWindowManager refactor * make AnnotationManager independent from MapView/MapboxMap, add IconManager, * make code unit testable * added some class level documentation (for internal use)
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java576
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java158
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java83
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java402
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java465
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java5
8 files changed, 943 insertions, 766 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
index e17165ae49..36f43abb11 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
@@ -400,7 +400,7 @@ public class MarkerViewManager {
*/
public void invalidateViewMarkersInVisibleRegion() {
RectF mapViewRect = new RectF(0, 0, mapView.getWidth(), mapView.getHeight());
- List<MarkerView> markers = mapView.getMarkerViewsInRect(mapViewRect);
+ List<MarkerView> markers = mapboxMap.getMarkerViewsInRect(mapViewRect);
View convertView;
// remove old markers
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
new file mode 100644
index 0000000000..0eae8eb0a9
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
@@ -0,0 +1,576 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.RectF;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.util.LongSparseArray;
+
+import com.mapbox.mapboxsdk.annotations.Annotation;
+import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
+import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
+import com.mapbox.mapboxsdk.annotations.Icon;
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
+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 java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Responsible for managing and tracking state of Annotations linked to Map. All events related to
+ * annotations that occur on {@link MapboxMap} are forwarded to this class.
+ * <p>
+ * Responsible for referencing {@link InfoWindowManager} and {@link MarkerViewManager}.
+ * </p>
+ * <p>
+ * Exposes convenience methods to add/remove/update all subtypes of annotations found in com.mapbox.mapboxsdk.annotations.
+ * </p>
+ */
+class AnnotationManager {
+
+ private NativeMapView nativeMapView;
+ private IconManager iconManager;
+ private InfoWindowManager infoWindowManager;
+ private MarkerViewManager markerViewManager;
+
+ private LongSparseArray<Annotation> annotations;
+ private List<Marker> selectedMarkers;
+
+ private MapboxMap.OnMarkerClickListener onMarkerClickListener;
+
+ AnnotationManager(NativeMapView view, IconManager iconManager, InfoWindowManager manager) {
+ this.nativeMapView = view;
+ this.iconManager = iconManager;
+ this.infoWindowManager = manager;
+ this.selectedMarkers = new ArrayList<>();
+ this.annotations = new LongSparseArray<>();
+ }
+
+ //
+ // Annotations
+ //
+
+ Annotation getAnnotation(long id) {
+ return annotations.get(id);
+ }
+
+ List<Annotation> getAnnotations() {
+ List<Annotation> annotations = new ArrayList<>();
+ for (int i = 0; i < this.annotations.size(); i++) {
+ annotations.add(this.annotations.get(this.annotations.keyAt(i)));
+ }
+ return annotations;
+ }
+
+ void removeAnnotation(@NonNull Annotation annotation) {
+ if (annotation instanceof Marker) {
+ Marker marker = (Marker) annotation;
+ marker.hideInfoWindow();
+ if (marker instanceof MarkerView) {
+ markerViewManager.removeMarkerView((MarkerView) marker);
+ }
+ }
+ long id = annotation.getId();
+ if (nativeMapView != null) {
+ nativeMapView.removeAnnotation(id);
+ }
+ annotations.remove(id);
+ }
+
+ void removeAnnotation(long id) {
+ if (nativeMapView != null) {
+ nativeMapView.removeAnnotation(id);
+ }
+ annotations.remove(id);
+ }
+
+ void removeAnnotations(@NonNull List<? extends Annotation> annotationList) {
+ int count = annotationList.size();
+ long[] ids = new long[count];
+ for (int i = 0; i < count; i++) {
+ Annotation annotation = annotationList.get(i);
+ if (annotation instanceof Marker) {
+ Marker marker = (Marker) annotation;
+ marker.hideInfoWindow();
+ if (marker instanceof MarkerView) {
+ markerViewManager.removeMarkerView((MarkerView) marker);
+ }
+ }
+ ids[i] = annotationList.get(i).getId();
+ }
+
+ if (nativeMapView != null) {
+ nativeMapView.removeAnnotations(ids);
+ }
+
+ for (long id : ids) {
+ annotations.remove(id);
+ }
+ }
+
+ void removeAnnotations() {
+ Annotation annotation;
+ int count = annotations.size();
+ long[] ids = new long[count];
+ for (int i = 0; i < count; i++) {
+ ids[i] = annotations.keyAt(i);
+ annotation = annotations.get(ids[i]);
+ if (annotation instanceof Marker) {
+ Marker marker = (Marker) annotation;
+ marker.hideInfoWindow();
+ if (marker instanceof MarkerView) {
+ markerViewManager.removeMarkerView((MarkerView) marker);
+ }
+ }
+ }
+
+ if (nativeMapView != null) {
+ nativeMapView.removeAnnotations(ids);
+ }
+
+ annotations.clear();
+ }
+
+ //
+ // Markers
+ //
+
+ Marker addMarker(@NonNull BaseMarkerOptions markerOptions, @NonNull MapboxMap mapboxMap) {
+ Marker marker = prepareMarker(markerOptions);
+ long id = nativeMapView != null ? nativeMapView.addMarker(marker) : 0;
+ marker.setMapboxMap(mapboxMap);
+ marker.setId(id);
+ annotations.put(id, marker);
+ return marker;
+ }
+
+ List<Marker> addMarkers(@NonNull List<? extends BaseMarkerOptions> markerOptionsList, @NonNull MapboxMap mapboxMap) {
+ int count = markerOptionsList.size();
+ List<Marker> markers = new ArrayList<>(count);
+ if (count > 0) {
+ BaseMarkerOptions markerOptions;
+ Marker marker;
+ for (int i = 0; i < count; i++) {
+ markerOptions = markerOptionsList.get(i);
+ marker = prepareMarker(markerOptions);
+ markers.add(marker);
+ }
+
+ if (markers.size() > 0) {
+ long[] ids = null;
+ if (nativeMapView != null) {
+ ids = nativeMapView.addMarkers(markers);
+ }
+
+ long id = 0;
+ Marker m;
+ for (int i = 0; i < markers.size(); i++) {
+ m = markers.get(i);
+ m.setMapboxMap(mapboxMap);
+ if (ids != null) {
+ id = ids[i];
+ } else {
+ //unit test
+ id++;
+ }
+ m.setId(id);
+ annotations.put(id, m);
+ }
+
+ }
+ }
+ return markers;
+ }
+
+ private Marker prepareMarker(BaseMarkerOptions markerOptions) {
+ Marker marker = markerOptions.getMarker();
+ Icon icon = iconManager.loadIconForMarker(marker);
+ marker.setTopOffsetPixels(iconManager.getTopOffsetPixelsForIcon(icon));
+ return marker;
+ }
+
+ MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, @NonNull MapboxMap mapboxMap) {
+ MarkerView marker = prepareViewMarker(markerOptions);
+ marker.setMapboxMap(mapboxMap);
+ long id = nativeMapView.addMarker(marker);
+ marker.setId(id);
+ annotations.put(id, marker);
+ markerViewManager.invalidateViewMarkersInVisibleRegion();
+ return marker;
+ }
+
+ List<MarkerView> addMarkerViews(@NonNull List<? extends BaseMarkerViewOptions> markerViewOptions, @NonNull MapboxMap mapboxMap) {
+ List<MarkerView> markers = new ArrayList<>();
+ for (BaseMarkerViewOptions markerViewOption : markerViewOptions) {
+ MarkerView marker = prepareViewMarker(markerViewOption);
+ marker.setMapboxMap(mapboxMap);
+ long id = nativeMapView.addMarker(marker);
+ marker.setId(id);
+ annotations.put(id, marker);
+ markers.add(marker);
+ }
+ markerViewManager.invalidateViewMarkersInVisibleRegion();
+ return markers;
+ }
+
+ private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) {
+ MarkerView marker = markerViewOptions.getMarker();
+ iconManager.loadIconForMarkerView(marker);
+ return marker;
+ }
+
+ void updateMarker(@NonNull Marker updatedMarker, @NonNull MapboxMap mapboxMap) {
+ if (updatedMarker == null) {
+ return;
+ }
+
+ if (updatedMarker.getId() == -1) {
+ return;
+ }
+
+ if (!(updatedMarker instanceof MarkerView)) {
+ iconManager.ensureIconLoaded(updatedMarker, mapboxMap);
+ }
+
+ nativeMapView.updateMarker(updatedMarker);
+
+ int index = annotations.indexOfKey(updatedMarker.getId());
+ if (index > -1) {
+ annotations.setValueAt(index, updatedMarker);
+ }
+ }
+
+ List<Marker> getMarkers() {
+ List<Marker> markers = new ArrayList<>();
+ Annotation annotation;
+ for (int i = 0; i < annotations.size(); i++) {
+ annotation = annotations.get(annotations.keyAt(i));
+ if (annotation instanceof Marker) {
+ markers.add((Marker) annotation);
+ }
+ }
+ return markers;
+ }
+
+ void setOnMarkerClickListener(@Nullable MapboxMap.OnMarkerClickListener listener) {
+ onMarkerClickListener = listener;
+ }
+
+ void selectMarker(@NonNull Marker marker, @NonNull MapboxMap mapboxMap) {
+ if (selectedMarkers.contains(marker)) {
+ return;
+ }
+
+ // Need to deselect any currently selected annotation first
+ if (!infoWindowManager.isAllowConcurrentMultipleOpenInfoWindows()) {
+ deselectMarkers();
+ }
+
+ boolean handledDefaultClick = false;
+ if (onMarkerClickListener != null) {
+ // end developer has provided a custom click listener
+ handledDefaultClick = onMarkerClickListener.onMarkerClick(marker);
+ }
+
+ if (!handledDefaultClick) {
+ if (marker instanceof MarkerView) {
+ markerViewManager.select((MarkerView) marker, false);
+ markerViewManager.ensureInfoWindowOffset((MarkerView) marker);
+ }
+
+ if (infoWindowManager.isInfoWindowValidForMarker(marker) || infoWindowManager.getInfoWindowAdapter() != null) {
+ infoWindowManager.getInfoWindows().add(marker.showInfoWindow(mapboxMap, mapboxMap.getMapView()));
+ }
+ }
+
+ selectedMarkers.add(marker);
+ }
+
+ void deselectMarkers() {
+ if (selectedMarkers.isEmpty()) {
+ return;
+ }
+
+ for (Marker marker : selectedMarkers) {
+ if (marker.isInfoWindowShown()) {
+ marker.hideInfoWindow();
+ }
+
+ if (marker instanceof MarkerView) {
+ markerViewManager.deselect((MarkerView) marker, false);
+ }
+ }
+
+ // Removes all selected markers from the list
+ selectedMarkers.clear();
+ }
+
+ void deselectMarker(@NonNull Marker marker) {
+ if (!selectedMarkers.contains(marker)) {
+ return;
+ }
+
+ if (marker.isInfoWindowShown()) {
+ marker.hideInfoWindow();
+ }
+
+ if (marker instanceof MarkerView) {
+ markerViewManager.deselect((MarkerView) marker, false);
+ }
+
+ selectedMarkers.remove(marker);
+ }
+
+ List<Marker> getSelectedMarkers() {
+ return selectedMarkers;
+ }
+
+ public List<Marker> getMarkersInRect(@NonNull RectF rect) {
+ long[] ids = nativeMapView.queryPointAnnotations(rect);
+
+ List<Long> idsList = new ArrayList<>(ids.length);
+ for (long id : ids) {
+ idsList.add(id);
+ }
+
+ List<Marker> annotations = new ArrayList<>(ids.length);
+ List<Annotation> annotationList = getAnnotations();
+ int count = annotationList.size();
+ for (int i = 0; i < count; i++) {
+ Annotation annotation = annotationList.get(i);
+ if (annotation instanceof com.mapbox.mapboxsdk.annotations.Marker && idsList.contains(annotation.getId())) {
+ annotations.add((com.mapbox.mapboxsdk.annotations.Marker) annotation);
+ }
+ }
+
+ return new ArrayList<>(annotations);
+ }
+
+ public List<MarkerView> getMarkerViewsInRect(@NonNull RectF rect) {
+ long[] ids = nativeMapView.queryPointAnnotations(rect);
+
+ List<Long> idsList = new ArrayList<>(ids.length);
+ for (long id : ids) {
+ idsList.add(id);
+ }
+
+ List<MarkerView> annotations = new ArrayList<>(ids.length);
+ List<Annotation> annotationList = getAnnotations();
+ int count = annotationList.size();
+ for (int i = 0; i < count; i++) {
+ Annotation annotation = annotationList.get(i);
+ if (annotation instanceof MarkerView) {
+ annotations.add((MarkerView) annotation);
+ }
+ }
+
+ return new ArrayList<>(annotations);
+ }
+
+ //
+ // Polygons
+ //
+
+ Polygon addPolygon(@NonNull PolygonOptions polygonOptions, @NonNull MapboxMap mapboxMap) {
+ Polygon polygon = polygonOptions.getPolygon();
+ if (!polygon.getPoints().isEmpty()) {
+ long id = nativeMapView != null ? nativeMapView.addPolygon(polygon) : 0;
+ polygon.setId(id);
+ polygon.setMapboxMap(mapboxMap);
+ annotations.put(id, polygon);
+ }
+ return polygon;
+ }
+
+ List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList, @NonNull MapboxMap mapboxMap) {
+ int count = polygonOptionsList.size();
+
+ Polygon polygon;
+ List<Polygon> polygons = new ArrayList<>(count);
+ if (count > 0) {
+ for (PolygonOptions polygonOptions : polygonOptionsList) {
+ polygon = polygonOptions.getPolygon();
+ if (!polygon.getPoints().isEmpty()) {
+ polygons.add(polygon);
+ }
+ }
+
+ long[] ids = null;
+ if (nativeMapView != null) {
+ ids = nativeMapView.addPolygons(polygons);
+ }
+
+ long id = 0;
+ for (int i = 0; i < polygons.size(); i++) {
+ polygon = polygons.get(i);
+ polygon.setMapboxMap(mapboxMap);
+ if (ids != null) {
+ id = ids[i];
+ } else {
+ // unit test
+ id++;
+ }
+ polygon.setId(id);
+ annotations.put(id, polygon);
+ }
+ }
+ return polygons;
+ }
+
+ void updatePolygon(Polygon polygon) {
+ if (polygon == null) {
+ return;
+ }
+
+ if (polygon.getId() == -1) {
+ return;
+ }
+
+ nativeMapView.updatePolygon(polygon);
+
+ int index = annotations.indexOfKey(polygon.getId());
+ if (index > -1) {
+ annotations.setValueAt(index, polygon);
+ }
+ }
+
+ List<Polygon> getPolygons() {
+ List<Polygon> polygons = new ArrayList<>();
+ Annotation annotation;
+ for (int i = 0; i < annotations.size(); i++) {
+ annotation = annotations.get(annotations.keyAt(i));
+ if (annotation instanceof Polygon) {
+ polygons.add((Polygon) annotation);
+ }
+ }
+ return polygons;
+ }
+
+ //
+ // Polylines
+ //
+
+ Polyline addPolyline(@NonNull PolylineOptions polylineOptions, @NonNull MapboxMap mapboxMap) {
+ Polyline polyline = polylineOptions.getPolyline();
+ if (!polyline.getPoints().isEmpty()) {
+ long id = nativeMapView != null ? nativeMapView.addPolyline(polyline) : 0;
+ polyline.setMapboxMap(mapboxMap);
+ polyline.setId(id);
+ annotations.put(id, polyline);
+ }
+ return polyline;
+ }
+
+ List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList, @NonNull MapboxMap mapboxMap) {
+ int count = polylineOptionsList.size();
+ Polyline polyline;
+ List<Polyline> polylines = new ArrayList<>(count);
+
+ if (count > 0) {
+ for (PolylineOptions options : polylineOptionsList) {
+ polyline = options.getPolyline();
+ if (!polyline.getPoints().isEmpty()) {
+ polylines.add(polyline);
+ }
+ }
+
+ long[] ids = null;
+ if (nativeMapView != null) {
+ ids = nativeMapView.addPolylines(polylines);
+ }
+
+ long id = 0;
+ Polyline p;
+
+ for (int i = 0; i < polylines.size(); i++) {
+ p = polylines.get(i);
+ p.setMapboxMap(mapboxMap);
+ if (ids != null) {
+ id = ids[i];
+ } else {
+ // unit test
+ id++;
+ }
+ p.setId(id);
+ annotations.put(id, p);
+ }
+ }
+ return polylines;
+ }
+
+ void updatePolyline(Polyline polyline) {
+ if (polyline == null) {
+ return;
+ }
+
+ if (polyline.getId() == -1) {
+ return;
+ }
+
+ nativeMapView.updatePolyline(polyline);
+
+ int index = annotations.indexOfKey(polyline.getId());
+ if (index > -1) {
+ annotations.setValueAt(index, polyline);
+ }
+ }
+
+ List<Polyline> getPolylines() {
+ List<Polyline> polylines = new ArrayList<>();
+ Annotation annotation;
+ for (int i = 0; i < annotations.size(); i++) {
+ annotation = annotations.get(annotations.keyAt(i));
+ if (annotation instanceof Polyline) {
+ polylines.add((Polyline) annotation);
+ }
+ }
+ return polylines;
+ }
+
+ //
+ // MarkerViewManager
+ //
+
+ MarkerViewManager getMarkerViewManager(MapboxMap mapboxMap) {
+ if (markerViewManager == null) {
+ this.markerViewManager = new MarkerViewManager(mapboxMap, mapboxMap.getMapView());
+ }
+ return markerViewManager;
+ }
+
+ void adjustTopOffsetPixels(MapboxMap mapboxMap) {
+ int count = annotations.size();
+ for (int i = 0; i < count; i++) {
+ Annotation annotation = annotations.get(i);
+ if (annotation instanceof Marker) {
+ Marker marker = (Marker) annotation;
+ marker.setTopOffsetPixels(
+ iconManager.getTopOffsetPixelsForIcon(marker.getIcon()));
+ }
+ }
+
+ for (Marker marker : selectedMarkers) {
+ if (marker.isInfoWindowShown()) {
+ marker.hideInfoWindow();
+ marker.showInfoWindow(mapboxMap, mapboxMap.getMapView());
+ }
+ }
+ }
+
+ void reloadMarkers() {
+ int count = annotations.size();
+ for (int i = 0; i < count; i++) {
+ Annotation annotation = annotations.get(i);
+ if (annotation instanceof Marker) {
+ Marker marker = (Marker) annotation;
+ nativeMapView.removeAnnotation(annotation.getId());
+ long newId = nativeMapView.addMarker(marker);
+ marker.setId(newId);
+ }
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
new file mode 100644
index 0000000000..71a9d4a2da
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
@@ -0,0 +1,158 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.Bitmap;
+import android.util.DisplayMetrics;
+
+import com.mapbox.mapboxsdk.annotations.Icon;
+import com.mapbox.mapboxsdk.annotations.IconFactory;
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.exceptions.IconBitmapChangedException;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Responsible for managing icons added to the Map.
+ * <p>
+ * Maintains a {@link List} of {@link Icon} and is responsible for initialising default markers and
+ * setting up {@link MarkerView} annotation ghosting.
+ * </p>
+ * <p>
+ * Keep track of icons added and the resulting average icon size. This is used internally by our
+ * gestures detection to calculate the size of a touch target.
+ * </p>
+ */
+class IconManager {
+
+ private NativeMapView nativeMapView;
+ private List<Icon> icons;
+
+ private int averageIconHeight;
+ private int averageIconWidth;
+
+ IconManager(NativeMapView nativeMapView) {
+ this.nativeMapView = nativeMapView;
+ this.icons = new ArrayList<>();
+ // load transparent icon for MarkerView to trace actual markers, see #6352
+ loadIcon(IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, IconFactory.ICON_MARKERVIEW_BITMAP));
+ }
+
+ Icon loadIconForMarker(Marker marker) {
+ Icon icon = marker.getIcon();
+
+ // calculating average before adding
+ int iconSize = icons.size() + 1;
+
+ // TODO replace former if case with anchor implementation,
+ // current workaround for having extra pixels is diving height by 2
+ if (icon == null) {
+ icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker();
+ Bitmap bitmap = icon.getBitmap();
+ averageIconHeight = averageIconHeight + (bitmap.getHeight() / 2 - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
+ marker.setIcon(icon);
+ } else {
+ Bitmap bitmap = icon.getBitmap();
+ averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
+ }
+
+ if (!icons.contains(icon)) {
+ icons.add(icon);
+ loadIcon(icon);
+ } else {
+ Icon oldIcon = icons.get(icons.indexOf(icon));
+ if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
+ throw new IconBitmapChangedException();
+ }
+ }
+ return icon;
+ }
+
+ Icon loadIconForMarkerView(MarkerView marker) {
+ Icon icon = marker.getIcon();
+ int iconSize = icons.size() + 1;
+ if (icon == null) {
+ icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarkerView();
+ marker.setIcon(icon);
+ }
+ Bitmap bitmap = icon.getBitmap();
+ averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
+ averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
+ if (!icons.contains(icon)) {
+ icons.add(icon);
+ } else {
+ Icon oldIcon = icons.get(icons.indexOf(icon));
+ if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
+ throw new IconBitmapChangedException();
+ }
+ }
+ return icon;
+ }
+
+ int getTopOffsetPixelsForIcon(Icon icon) {
+ return (int) (nativeMapView.getTopOffsetPixelsForAnnotationSymbol(icon.getId()) * nativeMapView.getPixelRatio());
+ }
+
+ void loadIcon(Icon icon) {
+ Bitmap bitmap = icon.getBitmap();
+ String id = icon.getId();
+ if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
+ bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
+ }
+ ByteBuffer buffer = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight());
+ bitmap.copyPixelsToBuffer(buffer);
+
+ float density = bitmap.getDensity();
+ if (density == Bitmap.DENSITY_NONE) {
+ density = DisplayMetrics.DENSITY_DEFAULT;
+ }
+ float scale = density / DisplayMetrics.DENSITY_DEFAULT;
+ nativeMapView.addAnnotationIcon(
+ id,
+ bitmap.getWidth(),
+ bitmap.getHeight(),
+ scale, buffer.array());
+ }
+
+ void reloadIcons() {
+ int count = icons.size();
+ for (int i = 0; i < count; i++) {
+ Icon icon = icons.get(i);
+ loadIcon(icon);
+ }
+ }
+
+ void ensureIconLoaded(Marker marker, MapboxMap mapboxMap) {
+ Icon icon = marker.getIcon();
+ if (icon == null) {
+ icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker();
+ marker.setIcon(icon);
+ }
+ if (!icons.contains(icon)) {
+ icons.add(icon);
+ loadIcon(icon);
+ } else {
+ Icon oldIcon = icons.get(icons.indexOf(icon));
+ if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
+ throw new IconBitmapChangedException();
+ }
+ }
+
+ // this seems to be a costly operation according to the profiler so I'm trying to save some calls
+ Marker previousMarker = marker.getId() != -1 ? (Marker) mapboxMap.getAnnotation(marker.getId()) : null;
+ if (previousMarker == null || previousMarker.getIcon() == null || previousMarker.getIcon() != marker.getIcon()) {
+ marker.setTopOffsetPixels(getTopOffsetPixelsForIcon(icon));
+ }
+ }
+
+ int getAverageIconHeight() {
+ return averageIconHeight;
+ }
+
+ int getAverageIconWidth() {
+ return averageIconWidth;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java
new file mode 100644
index 0000000000..7b58807973
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java
@@ -0,0 +1,83 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+
+import com.mapbox.mapboxsdk.annotations.InfoWindow;
+import com.mapbox.mapboxsdk.annotations.Marker;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Responsible for managing InfoWindows shown on the Map.
+ * <p>
+ * Maintains a {@link List} of opened {@link InfoWindow} and tracks configurations as
+ * allowConcurrentMultipleInfoWindows which allows to have multiple {@link InfoWindow} open at the
+ * same time. Responsible for managing listeners as {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnInfoWindowClickListener}
+ * and {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnInfoWindowLongClickListener}.
+ * </p>
+ */
+class InfoWindowManager {
+
+ private List<InfoWindow> infoWindows;
+ private MapboxMap.InfoWindowAdapter infoWindowAdapter;
+ private boolean allowConcurrentMultipleInfoWindows;
+
+ private MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener;
+ private MapboxMap.OnInfoWindowLongClickListener onInfoWindowLongClickListener;
+ private MapboxMap.OnInfoWindowCloseListener onInfoWindowCloseListener;
+
+ InfoWindowManager() {
+ this.infoWindows = new ArrayList<>();
+ }
+
+ void setInfoWindowAdapter(@Nullable MapboxMap.InfoWindowAdapter infoWindowAdapter) {
+ this.infoWindowAdapter = infoWindowAdapter;
+ }
+
+ MapboxMap.InfoWindowAdapter getInfoWindowAdapter() {
+ return infoWindowAdapter;
+ }
+
+ void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) {
+ allowConcurrentMultipleInfoWindows = allow;
+ }
+
+ boolean isAllowConcurrentMultipleOpenInfoWindows() {
+ return allowConcurrentMultipleInfoWindows;
+ }
+
+ List<InfoWindow> getInfoWindows() {
+ return infoWindows;
+ }
+
+ boolean isInfoWindowValidForMarker(@NonNull Marker marker) {
+ return !TextUtils.isEmpty(marker.getTitle()) || !TextUtils.isEmpty(marker.getSnippet());
+ }
+
+ void setOnInfoWindowClickListener(@Nullable MapboxMap.OnInfoWindowClickListener listener) {
+ onInfoWindowClickListener = listener;
+ }
+
+ MapboxMap.OnInfoWindowClickListener getOnInfoWindowClickListener() {
+ return onInfoWindowClickListener;
+ }
+
+ void setOnInfoWindowLongClickListener(@Nullable MapboxMap.OnInfoWindowLongClickListener listener) {
+ onInfoWindowLongClickListener = listener;
+ }
+
+ MapboxMap.OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() {
+ return onInfoWindowLongClickListener;
+ }
+
+ void setOnInfoWindowCloseListener(@Nullable MapboxMap.OnInfoWindowCloseListener listener) {
+ onInfoWindowCloseListener = listener;
+ }
+
+ MapboxMap.OnInfoWindowCloseListener getOnInfoWindowCloseListener() {
+ return onInfoWindowCloseListener;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
index 2ac95cf163..d1e2b1a253 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
@@ -35,7 +35,6 @@ import android.support.v4.view.ScaleGestureDetectorCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.InputDevice;
@@ -61,20 +60,15 @@ import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
import com.mapbox.mapboxsdk.MapboxAccountManager;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.annotations.Annotation;
-import com.mapbox.mapboxsdk.annotations.Icon;
-import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerView;
-import com.mapbox.mapboxsdk.annotations.Polygon;
-import com.mapbox.mapboxsdk.annotations.Polyline;
import com.mapbox.mapboxsdk.camera.CameraPosition;
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.exceptions.IconBitmapChangedException;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.LocationListener;
import com.mapbox.mapboxsdk.location.LocationServices;
@@ -87,7 +81,6 @@ import com.mapbox.mapboxsdk.utils.ColorUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
@@ -112,13 +105,12 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class MapView extends FrameLayout {
private MapboxMap mapboxMap;
+ private IconManager iconManager;
+ private AnnotationManager annotationManager;
+
private boolean initialLoad;
private boolean destroyed;
- private List<Icon> icons;
- private int averageIconHeight;
- private int averageIconWidth;
-
private NativeMapView nativeMapView;
private boolean hasSurface = false;
@@ -197,10 +189,7 @@ public class MapView extends FrameLayout {
initialLoad = true;
onMapReadyCallbackList = new ArrayList<>();
onMapChangedListener = new CopyOnWriteArrayList<>();
- mapboxMap = new MapboxMap(this);
- projection = mapboxMap.getProjection();
- icons = new ArrayList<>();
View view = LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this);
setWillNotDraw(false);
@@ -215,9 +204,10 @@ public class MapView extends FrameLayout {
}
nativeMapView = new NativeMapView(this);
-
- // load transparent icon for MarkerView to trace actual markers, see #6352
- loadIcon(IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, IconFactory.ICON_MARKERVIEW_BITMAP));
+ iconManager = new IconManager(nativeMapView);
+ mapboxMap = new MapboxMap(this, iconManager);
+ annotationManager = mapboxMap.getAnnotationManager();
+ projection = mapboxMap.getProjection();
// Ensure this view is interactable
setClickable(true);
@@ -474,9 +464,9 @@ public class MapView extends FrameLayout {
public void onMapChanged(@MapChange int change) {
if (change == DID_FINISH_LOADING_STYLE && initialLoad) {
initialLoad = false;
- reloadIcons();
- reloadMarkers();
- adjustTopOffsetPixels();
+ iconManager.reloadIcons();
+ annotationManager.reloadMarkers();
+ annotationManager.adjustTopOffsetPixels(mapboxMap);
// Notify listeners the map is ready
if (onMapReadyCallbackList.size() > 0) {
@@ -649,7 +639,7 @@ public class MapView extends FrameLayout {
nativeMapView.destroy();
nativeMapView = null;
}
-
+
void setFocalPoint(PointF focalPoint) {
if (focalPoint == null) {
// resetting focal point,
@@ -775,14 +765,6 @@ public class MapView extends FrameLayout {
return contentPaddingBottom;
}
- int getContentWidth() {
- return getWidth() - contentPaddingLeft - contentPaddingRight;
- }
-
- int getContentHeight() {
- return getHeight() - contentPaddingBottom - contentPaddingTop;
- }
-
//
// Zoom
//
@@ -846,10 +828,7 @@ public class MapView extends FrameLayout {
//
boolean isDebugActive() {
- if (destroyed) {
- return false;
- }
- return nativeMapView.getDebug();
+ return !destroyed && nativeMapView.getDebug();
}
void setDebugActive(boolean debugActive) {
@@ -1034,282 +1013,6 @@ public class MapView extends FrameLayout {
return nativeMapView.pixelForLatLng(location);
}
- //
- // Annotations
- //
-
- Icon loadIconForMarker(Marker marker) {
- Icon icon = marker.getIcon();
-
- // calculating average before adding
- int iconSize = icons.size() + 1;
-
- // TODO replace former if case with anchor implementation,
- // current workaround for having extra pixels is diving height by 2
- if (icon == null) {
- icon = IconFactory.getInstance(getContext()).defaultMarker();
- Bitmap bitmap = icon.getBitmap();
- averageIconHeight = averageIconHeight + (bitmap.getHeight() / 2 - averageIconHeight) / iconSize;
- averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
- marker.setIcon(icon);
- } else {
- Bitmap bitmap = icon.getBitmap();
- averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
- averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
- }
-
- if (!icons.contains(icon)) {
- icons.add(icon);
- loadIcon(icon);
- } else {
- Icon oldIcon = icons.get(icons.indexOf(icon));
- if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
- throw new IconBitmapChangedException();
- }
- }
- return icon;
- }
-
- Icon loadIconForMarkerView(MarkerView marker) {
- Icon icon = marker.getIcon();
- int iconSize = icons.size() + 1;
- if (icon == null) {
- icon = IconFactory.getInstance(getContext()).defaultMarkerView();
- marker.setIcon(icon);
- }
- Bitmap bitmap = icon.getBitmap();
- averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize;
- averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize;
- if (!icons.contains(icon)) {
- icons.add(icon);
- } else {
- Icon oldIcon = icons.get(icons.indexOf(icon));
- if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
- throw new IconBitmapChangedException();
- }
- }
- return icon;
- }
-
- void loadIcon(Icon icon) {
- if (destroyed) {
- return;
- }
- Bitmap bitmap = icon.getBitmap();
- String id = icon.getId();
- if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
- bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
- }
- ByteBuffer buffer = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight());
- bitmap.copyPixelsToBuffer(buffer);
-
- float density = bitmap.getDensity();
- if (density == Bitmap.DENSITY_NONE) {
- density = DisplayMetrics.DENSITY_DEFAULT;
- }
- float scale = density / DisplayMetrics.DENSITY_DEFAULT;
- nativeMapView.addAnnotationIcon(
- id,
- bitmap.getWidth(),
- bitmap.getHeight(),
- scale, buffer.array());
- }
-
- void reloadIcons() {
- int count = icons.size();
- for (int i = 0; i < count; i++) {
- Icon icon = icons.get(i);
- loadIcon(icon);
- }
- }
-
- void updateMarker(@NonNull Marker updatedMarker) {
- if (destroyed) {
- return;
- }
- if (updatedMarker == null) {
- Log.w(MapboxConstants.TAG, "marker was null, doing nothing");
- return;
- }
-
- if (updatedMarker.getId() == -1) {
- Log.w(MapboxConstants.TAG, "marker has an id of -1, possibly was not added yet, doing nothing");
- return;
- }
-
- if (!(updatedMarker instanceof MarkerView)) {
- ensureIconLoaded(updatedMarker);
- }
-
- nativeMapView.updateMarker(updatedMarker);
- }
-
-
- void updatePolygon(Polygon polygon) {
- if (destroyed) {
- return;
- }
-
- if (polygon == null) {
- Log.w(MapboxConstants.TAG, "polygon was null, doing nothing");
- return;
- }
-
- if (polygon.getId() == -1) {
- Log.w(MapboxConstants.TAG, "polygon has an id of -1, indicating the polygon was not added to the map yet.");
- return;
- }
-
- nativeMapView.updatePolygon(polygon);
- }
-
- void updatePolyline(Polyline polyline) {
- if (destroyed) {
- return;
- }
-
- if (polyline == null) {
- Log.w(MapboxConstants.TAG, "polygon was null, doing nothing");
- return;
- }
-
- if (polyline.getId() == -1) {
- Log.w(MapboxConstants.TAG, "polygon has an id of -1, indicating the polygon was not added to the map yet.");
- return;
- }
-
- nativeMapView.updatePolyline(polyline);
- }
-
- private void ensureIconLoaded(Marker marker) {
- Icon icon = marker.getIcon();
- if (icon == null) {
- icon = IconFactory.getInstance(getContext()).defaultMarker();
- marker.setIcon(icon);
- }
- if (!icons.contains(icon)) {
- icons.add(icon);
- loadIcon(icon);
- } else {
- Icon oldIcon = icons.get(icons.indexOf(icon));
- if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) {
- throw new IconBitmapChangedException();
- }
- }
-
- // this seems to be a costly operation according to the profiler so I'm trying to save some calls
- Marker previousMarker = marker.getId() != -1 ? (Marker) mapboxMap.getAnnotation(marker.getId()) : null;
- if (previousMarker == null || previousMarker.getIcon() == null || previousMarker.getIcon() != marker.getIcon()) {
- marker.setTopOffsetPixels(getTopOffsetPixelsForIcon(icon));
- }
- }
-
- long addMarker(@NonNull Marker marker) {
- if (destroyed) {
- return 0L;
- }
- return nativeMapView.addMarker(marker);
- }
-
- long[] addMarkers(@NonNull List<Marker> markerList) {
- if (destroyed) {
- return new long[]{};
- }
- return nativeMapView.addMarkers(markerList);
- }
-
- long addPolyline(@NonNull Polyline polyline) {
- if (destroyed) {
- return 0L;
- }
- return nativeMapView.addPolyline(polyline);
- }
-
- long[] addPolylines(@NonNull List<Polyline> polylines) {
- if (destroyed) {
- return new long[]{};
- }
- return nativeMapView.addPolylines(polylines);
- }
-
- long addPolygon(@NonNull Polygon polygon) {
- if (destroyed) {
- return 0L;
- }
- return nativeMapView.addPolygon(polygon);
- }
-
- long[] addPolygons(@NonNull List<Polygon> polygons) {
- if (destroyed) {
- return new long[]{};
- }
- return nativeMapView.addPolygons(polygons);
- }
-
- void removeAnnotation(long id) {
- if (destroyed) {
- return;
- }
- nativeMapView.removeAnnotation(id);
- }
-
- void removeAnnotations(@NonNull long[] ids) {
- if (destroyed) {
- return;
- }
- nativeMapView.removeAnnotations(ids);
- }
-
- List<Marker> getMarkersInRect(@NonNull RectF rect) {
- if (destroyed || rect == null) {
- return new ArrayList<>();
- }
-
- long[] ids = nativeMapView.queryPointAnnotations(rect);
-
- List<Long> idsList = new ArrayList<>(ids.length);
- for (int i = 0; i < ids.length; i++) {
- idsList.add(ids[i]);
- }
-
- List<Marker> annotations = new ArrayList<>(ids.length);
- List<Annotation> annotationList = mapboxMap.getAnnotations();
- int count = annotationList.size();
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotationList.get(i);
- if (annotation instanceof Marker && idsList.contains(annotation.getId())) {
- annotations.add((Marker) annotation);
- }
- }
-
- return new ArrayList<>(annotations);
- }
-
- public List<MarkerView> getMarkerViewsInRect(@NonNull RectF rect) {
- if (destroyed || rect == null) {
- return new ArrayList<>();
- }
-
- long[] ids = nativeMapView.queryPointAnnotations(rect);
-
- List<Long> idsList = new ArrayList<>(ids.length);
- for (int i = 0; i < ids.length; i++) {
- idsList.add(ids[i]);
- }
-
- List<MarkerView> annotations = new ArrayList<>(ids.length);
- List<Annotation> annotationList = mapboxMap.getAnnotations();
- int count = annotationList.size();
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotationList.get(i);
- if (annotation instanceof MarkerView) {
- annotations.add((MarkerView) annotation);
- }
- }
-
- return new ArrayList<>(annotations);
- }
-
/**
* @return the ViewGroup containing the marker views
*/
@@ -1317,16 +1020,6 @@ public class MapView extends FrameLayout {
return markerViewContainer;
}
-
- int getTopOffsetPixelsForIcon(Icon icon) {
- if (destroyed) {
- return 0;
- }
-
- return (int) (nativeMapView.getTopOffsetPixelsForAnnotationSymbol(icon.getId())
- * screenDensity);
- }
-
void setContentPadding(int left, int top, int right, int bottom) {
if (destroyed) {
return;
@@ -1428,43 +1121,6 @@ public class MapView extends FrameLayout {
nativeMapView.flyTo(bearing, center, duration, pitch, zoom);
}
- private void adjustTopOffsetPixels() {
- List<Annotation> annotations = mapboxMap.getAnnotations();
- int count = annotations.size();
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotations.get(i);
- if (annotation instanceof Marker) {
- Marker marker = (Marker) annotation;
- marker.setTopOffsetPixels(
- getTopOffsetPixelsForIcon(marker.getIcon()));
- }
- }
-
- for (Marker marker : mapboxMap.getSelectedMarkers()) {
- if (marker.isInfoWindowShown()) {
- marker.hideInfoWindow();
- marker.showInfoWindow(mapboxMap, this);
- }
- }
- }
-
- private void reloadMarkers() {
- if (destroyed) {
- return;
- }
- List<Annotation> annotations = mapboxMap.getAnnotations();
- int count = annotations.size();
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotations.get(i);
- if (annotation instanceof Marker) {
- Marker marker = (Marker) annotation;
- nativeMapView.removeAnnotation(annotation.getId());
- long newId = nativeMapView.addMarker(marker);
- marker.setId(newId);
- }
- }
- }
-
//
// Rendering
//
@@ -1700,7 +1356,7 @@ public class MapView extends FrameLayout {
* @param xCoordinate Original x screen coordinate at start of gesture
* @param yCoordinate Original y screen cooridnate at start of gesture
*/
- private void trackGestureEvent(@NonNull String gestureId, @NonNull float xCoordinate, @NonNull float yCoordinate) {
+ private void trackGestureEvent(@NonNull String gestureId, float xCoordinate, float yCoordinate) {
LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
// NaN and Infinite checks to prevent JSON errors at send to server time
@@ -1732,7 +1388,7 @@ public class MapView extends FrameLayout {
* @param xCoordinate Original x screen coordinate at end of drag
* @param yCoordinate Orginal y screen coordinate at end of drag
*/
- private void trackGestureDragEndEvent(@NonNull float xCoordinate, @NonNull float yCoordinate) {
+ private void trackGestureDragEndEvent(float xCoordinate, float yCoordinate) {
LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
// NaN and Infinite checks to prevent JSON errors at send to server time
@@ -1900,12 +1556,12 @@ public class MapView extends FrameLayout {
float toleranceSides = 4 * screenDensity;
float toleranceTopBottom = 10 * screenDensity;
- RectF tapRect = new RectF((tapPoint.x - averageIconWidth / 2 - toleranceSides) / screenDensity,
- (tapPoint.y - averageIconHeight / 2 - toleranceTopBottom) / screenDensity,
- (tapPoint.x + averageIconWidth / 2 + toleranceSides) / screenDensity,
- (tapPoint.y + averageIconHeight / 2 + toleranceTopBottom) / screenDensity);
+ RectF tapRect = new RectF((tapPoint.x - iconManager.getAverageIconWidth() / 2 - toleranceSides) / screenDensity,
+ (tapPoint.y - iconManager.getAverageIconHeight() / 2 - toleranceTopBottom) / screenDensity,
+ (tapPoint.x + iconManager.getAverageIconWidth() / 2 + toleranceSides) / screenDensity,
+ (tapPoint.y + iconManager.getAverageIconHeight() / 2 + toleranceTopBottom) / screenDensity);
- List<Marker> nearbyMarkers = getMarkersInRect(tapRect);
+ List<Marker> nearbyMarkers = annotationManager.getMarkersInRect(tapRect);
long newSelectedMarkerId = -1;
if (nearbyMarkers != null && nearbyMarkers.size() > 0) {
@@ -2487,7 +2143,7 @@ public class MapView extends FrameLayout {
// Track if we have been cancelled
private boolean cancelled;
- public TrackballLongPressTimeOut() {
+ TrackballLongPressTimeOut() {
cancelled = false;
}
@@ -2713,13 +2369,6 @@ public class MapView extends FrameLayout {
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
- /**
- * Reset the tracking modes as necessary. Location tracking is reset if the map center is changed,
- * bearing tracking if there is a rotation.
- *
- * @param translate
- * @param rotate
- */
void resetTrackingModesIfRequired(boolean translate, boolean rotate) {
TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
@@ -2881,7 +2530,7 @@ public class MapView extends FrameLayout {
private Bitmap bitmap;
private MapboxMap.SnapshotReadyCallback callback;
- public SnapshotRequest(Bitmap bitmap, MapboxMap.SnapshotReadyCallback callback) {
+ SnapshotRequest(Bitmap bitmap, MapboxMap.SnapshotReadyCallback callback) {
this.bitmap = bitmap;
this.callback = callback;
}
@@ -2921,7 +2570,7 @@ public class MapView extends FrameLayout {
private static final int ATTRIBUTION_INDEX_TELEMETRY_SETTINGS = 3;
private MapView mapView;
- public AttributionOnClickListener(MapView mapView) {
+ AttributionOnClickListener(MapView mapView) {
super();
this.mapView = mapView;
}
@@ -2929,14 +2578,11 @@ public class MapView extends FrameLayout {
// Called when someone presses the attribution icon
@Override
public void onClick(View view) {
-
AlertDialog.Builder builder = new AlertDialog.Builder(mapView.getContext(), R.style.mapbox_AlertDialogStyle);
builder.setTitle(R.string.mapbox_attributionsDialogTitle);
String[] items = mapView.getContext().getResources().getStringArray(R.array.mapbox_attribution_names);
builder.setAdapter(new ArrayAdapter<>(mapView.getContext(), R.layout.mapbox_attribution_list_item, items), this);
- AlertDialog attributionDialog = builder.show();
-
- // TODO Change listview text color to mapView.getAttributionTintColor()
+ builder.show();
}
// Called when someone selects an attribution, 'Improve this map' adds location data to the url
@@ -2993,7 +2639,7 @@ public class MapView extends FrameLayout {
private MapboxMap mapboxMap;
- public ZoomInvalidator(MapboxMap mapboxMap) {
+ ZoomInvalidator(MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
index b1f0984e3c..65b67c9ff1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
@@ -10,9 +10,7 @@ import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
-import android.support.v4.util.LongSparseArray;
import android.support.v4.util.Pools;
-import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -21,7 +19,6 @@ import com.mapbox.mapboxsdk.MapboxAccountManager;
import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
-import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
@@ -47,7 +44,6 @@ import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.services.commons.geojson.Feature;
import java.lang.reflect.ParameterizedType;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -70,23 +66,13 @@ public class MapboxMap {
private Projection projection;
private CameraPosition cameraPosition;
private boolean invalidCameraPosition;
- private LongSparseArray<Annotation> annotations;
-
- private List<Marker> selectedMarkers;
- private MarkerViewManager markerViewManager;
-
- private List<InfoWindow> infoWindows;
- private MapboxMap.InfoWindowAdapter infoWindowAdapter;
private boolean myLocationEnabled;
- private boolean allowConcurrentMultipleInfoWindows;
private MapboxMap.OnMapClickListener onMapClickListener;
private MapboxMap.OnMapLongClickListener onMapLongClickListener;
- private MapboxMap.OnMarkerClickListener onMarkerClickListener;
- private MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener;
- private MapboxMap.OnInfoWindowLongClickListener onInfoWindowLongClickListener;
- private MapboxMap.OnInfoWindowCloseListener onInfoWindowCloseListener;
+
+
private MapboxMap.OnFlingListener onFlingListener;
private MapboxMap.OnScrollListener onScrollListener;
private MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener;
@@ -94,19 +80,20 @@ public class MapboxMap {
private MapboxMap.OnFpsChangedListener onFpsChangedListener;
private MapboxMap.OnCameraChangeListener onCameraChangeListener;
+ private AnnotationManager annotationManager;
+ private InfoWindowManager infoWindowManager;
+
private double maxZoomLevel = -1;
private double minZoomLevel = -1;
- MapboxMap(@NonNull MapView mapView) {
+ MapboxMap(@NonNull MapView mapView, IconManager iconManager) {
this.mapView = mapView;
this.mapView.addOnMapChangedListener(new MapChangeCameraPositionListener());
uiSettings = new UiSettings(mapView);
trackingSettings = new TrackingSettings(this.mapView, uiSettings);
projection = new Projection(mapView);
- annotations = new LongSparseArray<>();
- selectedMarkers = new ArrayList<>();
- infoWindows = new ArrayList<>();
- markerViewManager = new MarkerViewManager(this, mapView);
+ infoWindowManager = new InfoWindowManager();
+ annotationManager = new AnnotationManager(mapView.getNativeMapView(), iconManager, infoWindowManager);
}
// Style
@@ -220,7 +207,7 @@ public class MapboxMap {
*/
@UiThread
public void setMinZoom(
- @FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) {
+ @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;
@@ -257,7 +244,7 @@ public class MapboxMap {
*/
@UiThread
public void setMaxZoom(
- @FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) {
+ @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;
@@ -600,7 +587,7 @@ public class MapboxMap {
* Invalidates the current camera position by reconstructing it from mbgl
*/
private void invalidateCameraPosition() {
- if(invalidCameraPosition) {
+ if (invalidCameraPosition) {
invalidCameraPosition = false;
CameraPosition cameraPosition = mapView.invalidateCameraPosition();
@@ -801,7 +788,7 @@ public class MapboxMap {
@UiThread
@NonNull
public Marker addMarker(@NonNull MarkerOptions markerOptions) {
- return addMarker((BaseMarkerOptions) markerOptions);
+ return annotationManager.addMarker(markerOptions, this);
}
/**
@@ -817,12 +804,7 @@ public class MapboxMap {
@UiThread
@NonNull
public Marker addMarker(@NonNull BaseMarkerOptions markerOptions) {
- Marker marker = prepareMarker(markerOptions);
- long id = mapView.addMarker(marker);
- marker.setMapboxMap(this);
- marker.setId(id);
- annotations.put(id, marker);
- return marker;
+ return annotationManager.addMarker(markerOptions, this);
}
/**
@@ -838,29 +820,19 @@ public class MapboxMap {
@UiThread
@NonNull
public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions) {
- MarkerView marker = prepareViewMarker(markerOptions);
- marker.setMapboxMap(this);
- long id = mapView.addMarker(marker);
- marker.setId(id);
- annotations.put(id, marker);
- markerViewManager.invalidateViewMarkersInVisibleRegion();
- return marker;
+ return annotationManager.addMarker(markerOptions, this);
}
@UiThread
@NonNull
public List<MarkerView> addMarkerViews(@NonNull List<? extends BaseMarkerViewOptions> markerViewOptions) {
- List<MarkerView> markers = new ArrayList<>();
- for (BaseMarkerViewOptions markerViewOption : markerViewOptions) {
- MarkerView marker = prepareViewMarker(markerViewOption);
- marker.setMapboxMap(this);
- long id = mapView.addMarker(marker);
- marker.setId(id);
- annotations.put(id, marker);
- markers.add(marker);
- }
- markerViewManager.invalidateViewMarkersInVisibleRegion();
- return markers;
+ return annotationManager.addMarkerViews(markerViewOptions, this);
+ }
+
+ @UiThread
+ @NonNull
+ public List<MarkerView> getMarkerViewsInRect(@NonNull RectF rect) {
+ return annotationManager.getMarkerViewsInRect(rect);
}
/**
@@ -876,40 +848,7 @@ public class MapboxMap {
@UiThread
@NonNull
public List<Marker> addMarkers(@NonNull List<? extends BaseMarkerOptions> markerOptionsList) {
- int count = markerOptionsList.size();
- List<Marker> markers = new ArrayList<>(count);
- if (count > 0) {
- BaseMarkerOptions markerOptions;
- Marker marker;
- for (int i = 0; i < count; i++) {
- markerOptions = markerOptionsList.get(i);
- marker = prepareMarker(markerOptions);
- markers.add(marker);
- }
-
- if (markers.size() > 0) {
- long[] ids = mapView.addMarkers(markers);
-
- // if unittests or markers are correctly added to map
- if (ids == null || ids.length == markers.size()) {
- long id = 0;
- Marker m;
- for (int i = 0; i < markers.size(); i++) {
- m = markers.get(i);
- m.setMapboxMap(this);
- if (ids != null) {
- id = ids[i];
- } else {
- //unit test
- id++;
- }
- m.setId(id);
- annotations.put(id, m);
- }
- }
- }
- }
- return markers;
+ return annotationManager.addMarkers(markerOptionsList, this);
}
/**
@@ -921,42 +860,7 @@ public class MapboxMap {
*/
@UiThread
public void updateMarker(@NonNull Marker updatedMarker) {
- mapView.updateMarker(updatedMarker);
-
- int index = annotations.indexOfKey(updatedMarker.getId());
- if (index > -1) {
- annotations.setValueAt(index, updatedMarker);
- }
- }
-
- /**
- * Update a polygon on this map.
- *
- * @param polygon An updated polygon object.
- */
- @UiThread
- public void updatePolygon(Polygon polygon) {
- mapView.updatePolygon(polygon);
-
- int index = annotations.indexOfKey(polygon.getId());
- if (index > -1) {
- annotations.setValueAt(index, polygon);
- }
- }
-
- /**
- * Update a polyline on this map.
- *
- * @param polyline An updated polyline object.
- */
- @UiThread
- public void updatePolyline(Polyline polyline) {
- mapView.updatePolyline(polyline);
-
- int index = annotations.indexOfKey(polyline.getId());
- if (index > -1) {
- annotations.setValueAt(index, polyline);
- }
+ annotationManager.updateMarker(updatedMarker, this);
}
/**
@@ -968,14 +872,7 @@ public class MapboxMap {
@UiThread
@NonNull
public Polyline addPolyline(@NonNull PolylineOptions polylineOptions) {
- Polyline polyline = polylineOptions.getPolyline();
- if (!polyline.getPoints().isEmpty()) {
- long id = mapView.addPolyline(polyline);
- polyline.setMapboxMap(this);
- polyline.setId(id);
- annotations.put(id, polyline);
- }
- return polyline;
+ return annotationManager.addPolyline(polylineOptions, this);
}
/**
@@ -987,40 +884,17 @@ public class MapboxMap {
@UiThread
@NonNull
public List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList) {
- int count = polylineOptionsList.size();
- Polyline polyline;
- List<Polyline> polylines = new ArrayList<>(count);
-
- if (count > 0) {
- for (PolylineOptions options : polylineOptionsList) {
- polyline = options.getPolyline();
- if (!polyline.getPoints().isEmpty()) {
- polylines.add(polyline);
- }
- }
+ return annotationManager.addPolylines(polylineOptionsList, this);
+ }
- long[] ids = mapView.addPolylines(polylines);
-
- // if unit tests or polylines are correctly added to map
- if (ids == null || ids.length == polylines.size()) {
- long id = 0;
- Polyline p;
-
- for (int i = 0; i < polylines.size(); i++) {
- p = polylines.get(i);
- p.setMapboxMap(this);
- if (ids != null) {
- id = ids[i];
- } else {
- // unit test
- id++;
- }
- p.setId(id);
- annotations.put(id, p);
- }
- }
- }
- return polylines;
+ /**
+ * Update a polyline on this map.
+ *
+ * @param polyline An updated polyline object.
+ */
+ @UiThread
+ public void updatePolyline(Polyline polyline) {
+ annotationManager.updatePolyline(polyline);
}
/**
@@ -1032,14 +906,7 @@ public class MapboxMap {
@UiThread
@NonNull
public Polygon addPolygon(@NonNull PolygonOptions polygonOptions) {
- Polygon polygon = polygonOptions.getPolygon();
- if (!polygon.getPoints().isEmpty()) {
- long id = mapView.addPolygon(polygon);
- polygon.setId(id);
- polygon.setMapboxMap(this);
- annotations.put(id, polygon);
- }
- return polygon;
+ return annotationManager.addPolygon(polygonOptions, this);
}
/**
@@ -1051,38 +918,18 @@ public class MapboxMap {
@UiThread
@NonNull
public List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList) {
- int count = polygonOptionsList.size();
-
- Polygon polygon;
- List<Polygon> polygons = new ArrayList<>(count);
- if (count > 0) {
- for (PolygonOptions polygonOptions : polygonOptionsList) {
- polygon = polygonOptions.getPolygon();
- if (!polygon.getPoints().isEmpty()) {
- polygons.add(polygon);
- }
- }
+ return annotationManager.addPolygons(polygonOptionsList, this);
+ }
- long[] ids = mapView.addPolygons(polygons);
-
- // if unit tests or polygons correctly added to map
- if (ids == null || ids.length == polygons.size()) {
- long id = 0;
- for (int i = 0; i < polygons.size(); i++) {
- polygon = polygons.get(i);
- polygon.setMapboxMap(this);
- if (ids != null) {
- id = ids[i];
- } else {
- // unit test
- id++;
- }
- polygon.setId(id);
- annotations.put(id, polygon);
- }
- }
- }
- return polygons;
+
+ /**
+ * Update a polygon on this map.
+ *
+ * @param polygon An updated polygon object.
+ */
+ @UiThread
+ public void updatePolygon(Polygon polygon) {
+ annotationManager.updatePolygon(polygon);
}
/**
@@ -1095,7 +942,7 @@ public class MapboxMap {
*/
@UiThread
public void removeMarker(@NonNull Marker marker) {
- removeAnnotation(marker);
+ annotationManager.removeAnnotation(marker);
}
/**
@@ -1108,7 +955,7 @@ public class MapboxMap {
*/
@UiThread
public void removePolyline(@NonNull Polyline polyline) {
- removeAnnotation(polyline);
+ annotationManager.removeAnnotation(polyline);
}
/**
@@ -1121,7 +968,7 @@ public class MapboxMap {
*/
@UiThread
public void removePolygon(@NonNull Polygon polygon) {
- removeAnnotation(polygon);
+ annotationManager.removeAnnotation(polygon);
}
/**
@@ -1131,16 +978,7 @@ public class MapboxMap {
*/
@UiThread
public void removeAnnotation(@NonNull Annotation annotation) {
- if (annotation instanceof Marker) {
- Marker marker = (Marker) annotation;
- marker.hideInfoWindow();
- if (marker instanceof MarkerView) {
- markerViewManager.removeMarkerView((MarkerView) marker);
- }
- }
- long id = annotation.getId();
- mapView.removeAnnotation(id);
- annotations.remove(id);
+ annotationManager.removeAnnotation(annotation);
}
/**
@@ -1150,8 +988,7 @@ public class MapboxMap {
*/
@UiThread
public void removeAnnotation(long id) {
- mapView.removeAnnotation(id);
- annotations.remove(id);
+ annotationManager.removeAnnotation(id);
}
/**
@@ -1161,23 +998,7 @@ public class MapboxMap {
*/
@UiThread
public void removeAnnotations(@NonNull List<? extends Annotation> annotationList) {
- int count = annotationList.size();
- long[] ids = new long[count];
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotationList.get(i);
- if (annotation instanceof Marker) {
- Marker marker = (Marker) annotation;
- marker.hideInfoWindow();
- if (marker instanceof MarkerView) {
- markerViewManager.removeMarkerView((MarkerView) marker);
- }
- }
- ids[i] = annotationList.get(i).getId();
- }
- mapView.removeAnnotations(ids);
- for (long id : ids) {
- annotations.remove(id);
- }
+ annotationManager.removeAnnotations(annotationList);
}
/**
@@ -1185,22 +1006,7 @@ public class MapboxMap {
*/
@UiThread
public void removeAnnotations() {
- Annotation annotation;
- int count = annotations.size();
- long[] ids = new long[count];
- for (int i = 0; i < count; i++) {
- ids[i] = annotations.keyAt(i);
- annotation = annotations.get(ids[i]);
- if (annotation instanceof Marker) {
- Marker marker = (Marker) annotation;
- marker.hideInfoWindow();
- if (marker instanceof MarkerView) {
- markerViewManager.removeMarkerView((MarkerView) marker);
- }
- }
- }
- mapView.removeAnnotations(ids);
- annotations.clear();
+ annotationManager.removeAnnotations();
}
/**
@@ -1208,7 +1014,7 @@ public class MapboxMap {
*/
@UiThread
public void clear() {
- removeAnnotations();
+ annotationManager.removeAnnotations();
}
/**
@@ -1219,7 +1025,7 @@ public class MapboxMap {
*/
@Nullable
public Annotation getAnnotation(long id) {
- return annotations.get(id);
+ return annotationManager.getAnnotation(id);
}
/**
@@ -1230,11 +1036,7 @@ public class MapboxMap {
*/
@NonNull
public List<Annotation> getAnnotations() {
- List<Annotation> annotations = new ArrayList<>();
- for (int i = 0; i < this.annotations.size(); i++) {
- annotations.add(this.annotations.get(this.annotations.keyAt(i)));
- }
- return annotations;
+ return annotationManager.getAnnotations();
}
/**
@@ -1245,15 +1047,7 @@ public class MapboxMap {
*/
@NonNull
public List<Marker> getMarkers() {
- List<Marker> markers = new ArrayList<>();
- Annotation annotation;
- for (int i = 0; i < annotations.size(); i++) {
- annotation = annotations.get(annotations.keyAt(i));
- if (annotation instanceof Marker) {
- markers.add((Marker) annotation);
- }
- }
- return markers;
+ return annotationManager.getMarkers();
}
/**
@@ -1264,15 +1058,7 @@ public class MapboxMap {
*/
@NonNull
public List<Polygon> getPolygons() {
- List<Polygon> polygons = new ArrayList<>();
- Annotation annotation;
- for (int i = 0; i < annotations.size(); i++) {
- annotation = annotations.get(annotations.keyAt(i));
- if (annotation instanceof Polygon) {
- polygons.add((Polygon) annotation);
- }
- }
- return polygons;
+ return annotationManager.getPolygons();
}
/**
@@ -1283,15 +1069,18 @@ public class MapboxMap {
*/
@NonNull
public List<Polyline> getPolylines() {
- List<Polyline> polylines = new ArrayList<>();
- Annotation annotation;
- for (int i = 0; i < annotations.size(); i++) {
- annotation = annotations.get(annotations.keyAt(i));
- if (annotation instanceof Polyline) {
- polylines.add((Polyline) annotation);
- }
- }
- return polylines;
+ return annotationManager.getPolylines();
+ }
+
+ /**
+ * 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) {
+ annotationManager.setOnMarkerClickListener(listener);
}
/**
@@ -1310,34 +1099,7 @@ public class MapboxMap {
Log.w(MapboxConstants.TAG, "marker was null, so just returning");
return;
}
-
- if (selectedMarkers.contains(marker)) {
- return;
- }
-
- // Need to deselect any currently selected annotation first
- if (!isAllowConcurrentMultipleOpenInfoWindows()) {
- deselectMarkers();
- }
-
- boolean handledDefaultClick = false;
- if (onMarkerClickListener != null) {
- // end developer has provided a custom click listener
- handledDefaultClick = onMarkerClickListener.onMarkerClick(marker);
- }
-
- if (!handledDefaultClick) {
- if (marker instanceof MarkerView) {
- markerViewManager.select((MarkerView) marker, false);
- markerViewManager.ensureInfoWindowOffset((MarkerView) marker);
- }
-
- if (isInfoWindowValidForMarker(marker) || getInfoWindowAdapter() != null) {
- infoWindows.add(marker.showInfoWindow(this, mapView));
- }
- }
-
- selectedMarkers.add(marker);
+ annotationManager.selectMarker(marker, this);
}
/**
@@ -1345,22 +1107,7 @@ public class MapboxMap {
*/
@UiThread
public void deselectMarkers() {
- if (selectedMarkers.isEmpty()) {
- return;
- }
-
- for (Marker marker : selectedMarkers) {
- if (marker.isInfoWindowShown()) {
- marker.hideInfoWindow();
- }
-
- if (marker instanceof MarkerView) {
- markerViewManager.deselect((MarkerView) marker, false);
- }
- }
-
- // Removes all selected markers from the list
- selectedMarkers.clear();
+ annotationManager.deselectMarkers();
}
/**
@@ -1370,19 +1117,7 @@ public class MapboxMap {
*/
@UiThread
public void deselectMarker(@NonNull Marker marker) {
- if (!selectedMarkers.contains(marker)) {
- return;
- }
-
- if (marker.isInfoWindowShown()) {
- marker.hideInfoWindow();
- }
-
- if (marker instanceof MarkerView) {
- markerViewManager.deselect((MarkerView) marker, false);
- }
-
- selectedMarkers.remove(marker);
+ annotationManager.deselectMarker(marker);
}
/**
@@ -1392,20 +1127,7 @@ public class MapboxMap {
*/
@UiThread
public List<Marker> getSelectedMarkers() {
- return selectedMarkers;
- }
-
- private Marker prepareMarker(BaseMarkerOptions markerOptions) {
- Marker marker = markerOptions.getMarker();
- Icon icon = mapView.loadIconForMarker(marker);
- marker.setTopOffsetPixels(mapView.getTopOffsetPixelsForIcon(icon));
- return marker;
- }
-
- private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) {
- MarkerView marker = markerViewOptions.getMarker();
- mapView.loadIconForMarkerView(marker);
- return marker;
+ return annotationManager.getSelectedMarkers();
}
/**
@@ -1414,7 +1136,7 @@ public class MapboxMap {
* @return the associated MarkerViewManager
*/
public MarkerViewManager getMarkerViewManager() {
- return markerViewManager;
+ return annotationManager.getMarkerViewManager(this);
}
//
@@ -1433,7 +1155,7 @@ public class MapboxMap {
*/
@UiThread
public void setInfoWindowAdapter(@Nullable InfoWindowAdapter infoWindowAdapter) {
- this.infoWindowAdapter = infoWindowAdapter;
+ infoWindowManager.setInfoWindowAdapter(infoWindowAdapter);
}
/**
@@ -1444,7 +1166,7 @@ public class MapboxMap {
@UiThread
@Nullable
public InfoWindowAdapter getInfoWindowAdapter() {
- return infoWindowAdapter;
+ return infoWindowManager.getInfoWindowAdapter();
}
/**
@@ -1454,7 +1176,7 @@ public class MapboxMap {
*/
@UiThread
public void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) {
- allowConcurrentMultipleInfoWindows = allow;
+ infoWindowManager.setAllowConcurrentMultipleOpenInfoWindows(allow);
}
/**
@@ -1464,16 +1186,16 @@ public class MapboxMap {
*/
@UiThread
public boolean isAllowConcurrentMultipleOpenInfoWindows() {
- return allowConcurrentMultipleInfoWindows;
+ return infoWindowManager.isAllowConcurrentMultipleOpenInfoWindows();
}
// used by MapView
List<InfoWindow> getInfoWindows() {
- return infoWindows;
+ return infoWindowManager.getInfoWindows();
}
- private boolean isInfoWindowValidForMarker(@NonNull Marker marker) {
- return !TextUtils.isEmpty(marker.getTitle()) || !TextUtils.isEmpty(marker.getSnippet());
+ AnnotationManager getAnnotationManager() {
+ return annotationManager;
}
//
@@ -1611,17 +1333,6 @@ public class MapboxMap {
}
/**
- * 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) {
- onMarkerClickListener = listener;
- }
-
- /**
* 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.
@@ -1629,7 +1340,7 @@ public class MapboxMap {
*/
@UiThread
public void setOnInfoWindowClickListener(@Nullable OnInfoWindowClickListener listener) {
- onInfoWindowClickListener = listener;
+ infoWindowManager.setOnInfoWindowClickListener(listener);
}
/**
@@ -1639,7 +1350,7 @@ public class MapboxMap {
*/
@UiThread
public OnInfoWindowClickListener getOnInfoWindowClickListener() {
- return onInfoWindowClickListener;
+ return infoWindowManager.getOnInfoWindowClickListener();
}
/**
@@ -1650,7 +1361,7 @@ public class MapboxMap {
*/
@UiThread
public void setOnInfoWindowLongClickListener(@Nullable OnInfoWindowLongClickListener listener) {
- onInfoWindowLongClickListener = listener;
+ infoWindowManager.setOnInfoWindowLongClickListener(listener);
}
/**
@@ -1659,11 +1370,11 @@ public class MapboxMap {
* @return Current active InfoWindow long Click Listener
*/
public OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() {
- return onInfoWindowLongClickListener;
+ return infoWindowManager.getOnInfoWindowLongClickListener();
}
public void setOnInfoWindowCloseListener(@Nullable OnInfoWindowCloseListener listener) {
- onInfoWindowCloseListener = listener;
+ infoWindowManager.setOnInfoWindowCloseListener(listener);
}
/**
@@ -1673,7 +1384,7 @@ public class MapboxMap {
*/
@UiThread
public OnInfoWindowCloseListener getOnInfoWindowCloseListener() {
- return onInfoWindowCloseListener;
+ return infoWindowManager.getOnInfoWindowCloseListener();
}
//
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index 4e0ce33c5b..3e4e1dd305 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -34,14 +34,6 @@ import java.util.List;
// Class that wraps the native methods for convenience
final class NativeMapView {
- //
- // Static members
- //
-
- //
- // Instance members
- //
-
boolean destroyed = false;
// Holds the pointer to JNI NativeMapView
@@ -547,7 +539,7 @@ final class NativeMapView {
@NonNull
public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) {
Feature[] features = nativeQueryRenderedFeaturesForBox(
- nativeMapViewPtr,
+ nativeMapViewPtr,
coordinates.left / pixelRatio,
coordinates.top / pixelRatio,
coordinates.right / pixelRatio,
@@ -564,6 +556,14 @@ final class NativeMapView {
nativeSetAPIBaseURL(nativeMapViewPtr, baseUrl);
}
+ public float getPixelRatio() {
+ return pixelRatio;
+ }
+
+ public Context getContext() {
+ return mapView.getContext();
+ }
+
//
// Callbacks
//
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
index 9d0a1c0ad7..848a1e2abb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
@@ -79,10 +79,13 @@ public class MapboxMapTest {
@Mock
MapboxMap.OnMyBearingTrackingModeChangeListener mMyBearingTrackingModeChangeListener;
+ @Mock
+ IconManager iconManager;
+
@Before
public void beforeTest() {
MockitoAnnotations.initMocks(this);
- mMapboxMap = new MapboxMap(mMapView);
+ mMapboxMap = new MapboxMap(mMapView, iconManager);
}
@Test