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)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
return annotationManager.addPolylines(polylineOptionsList, this);
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
for (PolylineOptions options : polylineOptionsList) {
|
||||
polyline = options.getPolyline();
|
||||
if (!polyline.getPoints().isEmpty()) {
|
||||
polylines.add(polyline);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
return annotationManager.addPolygons(polygonOptionsList, this);
|
||||
}
|
||||
|
||||
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 = 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;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1610,17 +1332,6 @@ public class MapboxMap {
|
||||
return onMapLongClickListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -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
|
||||
//
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user