Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[android] Refactor annotations functions
Browse files Browse the repository at this point in the history
Fixes #2539
  • Loading branch information
Leith Bade committed Oct 8, 2015
1 parent 8b6f928 commit 576488f
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.graphics.drawable.BitmapDrawable;
import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
Expand Down Expand Up @@ -193,11 +192,11 @@ public final class MapView extends FrameLayout implements LocationListener, Comp
// Used for the compass
private CompassView mCompassView;

// Used for displaying annotation markers
// Used for displaying annotations
// Every annotation that has been added to the map
private final List<Annotation> mAnnotations = new ArrayList<>();
private List<Annotation> mAnnotationsNearLastTap = new ArrayList<>();
private Annotation mSelectedAnnotation;
private List<Marker> mMarkersNearLastTap = new ArrayList<>();
private Marker mSelectedMarker;
private InfoWindowAdapter mInfoWindowAdapter;

// Used for the Mapbox Logo
Expand Down Expand Up @@ -832,7 +831,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
public void onMapChanged(MapChange change) {
if (change.equals(MapChange.RegionWillChange) ||
change.equals(MapChange.RegionWillChangeAnimated)) {
deselectAnnotation();
deselectMarker();
}
}
});
Expand Down Expand Up @@ -1607,9 +1606,9 @@ public Marker addMarker(MarkerOptions markerOptions) {

// Load the default marker sprite
if (marker.getSprite() == null) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) ContextCompat.getDrawable(mContext, R.drawable.default_marker);
Bitmap bitmap = bitmapDrawable.getBitmap();
setSprite(DEFAULT_SPRITE, bitmap);
//BitmapDrawable bitmapDrawable = (BitmapDrawable) ContextCompat.getDrawable(mContext, R.drawable.default_marker);
//Bitmap bitmap = bitmapDrawable.getBitmap();
//setSprite(DEFAULT_SPRITE, bitmap);

// Red default marker is currently broken
marker.setSprite("default_marker");
Expand All @@ -1623,8 +1622,26 @@ public Marker addMarker(MarkerOptions markerOptions) {
return marker;
}

public List<Marker> addMarkers(List<Marker> markers) {
public List<Marker> addMarkers(List<MarkerOptions> markerOptionsList) {
List<Marker> markers = new ArrayList<>(markerOptionsList.size());
for (MarkerOptions markerOptions : markerOptionsList) {
Marker marker = markerOptions.getMarker();

// Load the default marker sprite
if (marker.getSprite() == null) {
//BitmapDrawable bitmapDrawable = (BitmapDrawable) ContextCompat.getDrawable(mContext, R.drawable.default_marker);
//Bitmap bitmap = bitmapDrawable.getBitmap();
//setSprite(DEFAULT_SPRITE, bitmap);

// Red default marker is currently broken
marker.setSprite("default_marker");
//marker.setSprite(DEFAULT_SPRITE);
}
markers.add(markerOptions.getMarker());
}

long[] ids = mNativeMapView.addMarkers(markers);

Marker m;
int count = markers.size();
for (int i = 0; i < count; i++) {
Expand All @@ -1633,7 +1650,8 @@ public List<Marker> addMarkers(List<Marker> markers) {
m.setMapView(this);
mAnnotations.add(m);
}
return markers;

return new ArrayList<>(markers);
}

public Polyline addPolyline(PolylineOptions polylineOptions) {
Expand All @@ -1645,6 +1663,16 @@ public Polyline addPolyline(PolylineOptions polylineOptions) {
return polyline;
}

public List<Polyline> addPolylines(List<PolylineOptions> polylineOptionsList) {
// TODO make faster in JNI
List<Polyline> polylines = new ArrayList<>(polylineOptionsList.size());
for (PolylineOptions polylineOptions : polylineOptionsList) {
polylines.add(addPolyline(polylineOptions));
}

return new ArrayList<>(polylines);
}

public Polygon addPolygon(PolygonOptions polygonOptions) {
Polygon polygon = polygonOptions.getPolygon();
long id = mNativeMapView.addPolygon(polygon);
Expand All @@ -1654,21 +1682,24 @@ public Polygon addPolygon(PolygonOptions polygonOptions) {
return polygon;
}

public List<Polygon> addPolygons(List<PolygonOptions> polygonOptions) {
List<Polygon> polygons = new ArrayList<>();
for (PolygonOptions popts : polygonOptions) {
polygons.add(popts.getPolygon());
public List<Polygon> addPolygons(List<PolygonOptions> polygonOptionsList) {
List<Polygon> polygons = new ArrayList<>(polygonOptionsList.size());
for (PolygonOptions polygonOptions : polygonOptionsList) {
polygons.add(polygonOptions.getPolygon());
}

long[] ids = mNativeMapView.addPolygons(polygons);

Polygon p;
int count = polygons.size();
for (int i = 0; i < polygons.size(); i++) {
polygons.get(i).setId(ids[i]);
polygons.get(i).setMapView(this);
mAnnotations.add(polygons.get(i));
p = polygons.get(i);
p.setId(ids[i]);
p.setMapView(this);
mAnnotations.add(p);
}

return Collections.unmodifiableList(polygons);
return new ArrayList<>(polygons);
}

private void removeAnnotationsWithId(long annotationId) {
Expand All @@ -1692,13 +1723,16 @@ public void removeAnnotation(Annotation annotation) {
mAnnotations.remove(annotation);
}

public void removeAnnotation(long annotationId) {
mNativeMapView.removeAnnotation(annotationId);
removeAnnotationsWithId(annotationId);
public void removeAnnotations(List<Annotation> annotationList) {
// TODO make faster in JNI
for (Annotation annotation : annotationList) {
removeAnnotation(annotation);
}
}

public void removeAnnotations() {
public void removeAllAnnotations() {
long[] ids = new long[mAnnotations.size()];

for (int i = 0; i < mAnnotations.size(); i++) {
Annotation annotation = mAnnotations.get(i);
long id = annotation.getId();
Expand All @@ -1707,28 +1741,33 @@ public void removeAnnotations() {
((Marker) annotation).hideInfoWindow();
}
}

mNativeMapView.removeAnnotations(ids);
mAnnotations.clear();
}

public List<Annotation> getAnnotations() {
return Collections.unmodifiableList(mAnnotations);
public List<Annotation> getAllAnnotations() {
return new ArrayList<>(mAnnotations);
}

public List<Annotation> getAnnotationsInBounds(BoundingBox bbox) {
List<Annotation> annotations = new ArrayList<>();
private List<Marker> getMarkersInBounds(BoundingBox bbox) {
// TODO: filter in JNI using C++ parameter to getAnnotationsInBounds
long[] ids = mNativeMapView.getAnnotationsInBounds(bbox);
List<Long> idsList = new ArrayList<>();

List<Long> idsList = new ArrayList<>(ids.length);
for (long id : ids) {
idsList.add(id);
}

List<Marker> annotations = new ArrayList<>(ids.length);
for (int i = 0; i < mAnnotations.size(); i++) {
Annotation annotation = mAnnotations.get(i);
if (annotation instanceof Marker && idsList.contains(annotation.getId())) {
annotations.add(annotation);
annotations.add((Marker)annotation);
}
}
return annotations;

return new ArrayList<>(annotations);
}

// Used by InfoWindow
Expand All @@ -1739,10 +1778,11 @@ public List<Annotation> getAnnotationsInBounds(BoundingBox bbox) {
/**
* Returns the distance spanned by one pixel at the specified latitude and current zoom level.
* <p/>
* The distance between pixels decreases as the latitude approaches the poles. This relationship parallels the relationship between longitudinal coordinates at different latitudes.
* The distance between pixels decreases as the latitude approaches the poles.
* This relationship parallels the relationship between longitudinal coordinates at different latitudes.
*
* @param latitude The latitude for which to return the value.
* @return The distance (in meters) spanned by a single pixel.
* @return The distance measured in meters.
*/
public double getMetersPerPixelAtLatitude(double latitude) {
return mNativeMapView.getMetersPerPixelAtLatitude(latitude, getZoomLevel());
Expand All @@ -1753,49 +1793,45 @@ float getScreenDensity() {
return mScreenDensity;
}

private void selectAnnotation(Annotation annotation) {
if (annotation == null) {
private void selectMarker(Marker marker) {
if (marker == null) {
return;
}

if (annotation == mSelectedAnnotation) {
if (marker == mSelectedMarker) {
return;
}

if (annotation instanceof Marker) {
// Need to deselect any currently selected annotation first
deselectAnnotation();

Marker marker = (Marker) annotation;
boolean handledDefaultClick = false;
if (mOnMarkerClickListener != null) {
// end developer has provided a custom click listener
handledDefaultClick = mOnMarkerClickListener.onMarkerClick(marker);
}
// Need to deselect any currently selected annotation first
deselectMarker();

if (mInfoWindowAdapter != null) {
// end developer is using a custom InfoWindowAdapter
View content = mInfoWindowAdapter.getInfoWindow(marker);
if (content != null) {
marker.showInfoWindow(content);
}
} else if (!handledDefaultClick) {
// default behaviour
// Can't do this as InfoWindow will get hidden
//setCenterCoordinate(marker.getPosition(), true);
marker.showInfoWindow();
}
boolean handledDefaultClick = false;
if (mOnMarkerClickListener != null) {
// end developer has provided a custom click listener
handledDefaultClick = mOnMarkerClickListener.onMarkerClick(marker);
}

mSelectedAnnotation = annotation;
if (mInfoWindowAdapter != null) {
// end developer is using a custom InfoWindowAdapter
View content = mInfoWindowAdapter.getInfoWindow(marker);
if (content != null) {
marker.showInfoWindow(content);
}
} else if (!handledDefaultClick) {
// default behaviour
// Can't do this as InfoWindow will get hidden
//setCenterCoordinate(marker.getPosition(), true);
marker.showInfoWindow();
}

mSelectedMarker = marker;
}

private void deselectAnnotation() {
if (mSelectedAnnotation != null && mSelectedAnnotation instanceof Marker) {
Marker marker = (Marker) mSelectedAnnotation;
if (marker.isInfoWindowShown()) {
marker.hideInfoWindow();
mSelectedAnnotation = null;
private void deselectMarker() {
if (mSelectedMarker != null) {
if (mSelectedMarker.isInfoWindowShown()) {
mSelectedMarker.hideInfoWindow();
mSelectedMarker = null;
}
}
}
Expand Down Expand Up @@ -2012,61 +2048,61 @@ public boolean onSingleTapConfirmed(MotionEvent e) {

BoundingBox tapBounds = BoundingBox.fromLatLngs(corners);

List<Annotation> nearbyAnnotations = getAnnotationsInBounds(tapBounds);
List<Marker> nearbyMarkers = getMarkersInBounds(tapBounds);

long newSelectedAnnotationID;
long newSelectedMarkerId;

if (nearbyAnnotations.size() > 0) {
if (nearbyMarkers.size() > 0) {

// there is at least one nearby annotation; select one
// there is at least one nearby marker; select one
//
// first, sort for comparison and iteration
Collections.sort(nearbyAnnotations);
Collections.sort(nearbyMarkers);

if (nearbyAnnotations == mAnnotationsNearLastTap) {
if (nearbyMarkers == mMarkersNearLastTap) {
// the selection candidates haven't changed; cycle through them
if (mSelectedAnnotation != null && (mSelectedAnnotation.getId() == mAnnotationsNearLastTap.get(mAnnotationsNearLastTap.size() - 1).getId())) {
// the selected annotation is the last in the set; cycle back to the first
// note: this could be the selected annotation if only one in set
newSelectedAnnotationID = mAnnotationsNearLastTap.get(0).getId();
} else if (mSelectedAnnotation != null) {
if (mSelectedMarker != null && (mSelectedMarker.getId() == mMarkersNearLastTap.get(mMarkersNearLastTap.size() - 1).getId())) {
// the selected marker is the last in the set; cycle back to the first
// note: this could be the selected marker if only one in set
newSelectedMarkerId = mMarkersNearLastTap.get(0).getId();
} else if (mSelectedMarker != null) {
// otherwise increment the selection through the candidates
long result = mAnnotationsNearLastTap.indexOf(mSelectedAnnotation);
newSelectedAnnotationID = mAnnotationsNearLastTap.get((int) result + 1).getId();
long result = mMarkersNearLastTap.indexOf(mSelectedMarker);
newSelectedMarkerId = mMarkersNearLastTap.get((int) result + 1).getId();
} else {
// no current selection; select the first one
newSelectedAnnotationID = mAnnotationsNearLastTap.get(0).getId();
newSelectedMarkerId = mMarkersNearLastTap.get(0).getId();
}
} else {
// start tracking a new set of nearby annotations
mAnnotationsNearLastTap = nearbyAnnotations;
// start tracking a new set of nearby markers
mMarkersNearLastTap = nearbyMarkers;

// select the first one
newSelectedAnnotationID = mAnnotationsNearLastTap.get(0).getId();
newSelectedMarkerId = mMarkersNearLastTap.get(0).getId();
}

} else {
// there are no nearby annotations; deselect if necessary
newSelectedAnnotationID = -1;
// there are no nearby markers; deselect if necessary
newSelectedMarkerId = -1;
}

if (newSelectedAnnotationID >= 0) {
if (newSelectedMarkerId >= 0) {

for (Annotation annotation : mAnnotations) {
if (annotation instanceof Marker) {
if (annotation.getId() == newSelectedAnnotationID) {
if (mSelectedAnnotation == null || annotation.getId() != mSelectedAnnotation.getId()) {
selectAnnotation(annotation);
if (annotation.getId() == newSelectedMarkerId) {
if (mSelectedMarker == null || annotation.getId() != mSelectedMarker.getId()) {
selectMarker((Marker)annotation);
}
break;
}
}
}

} else {
// deselect any selected annotation
if (mSelectedAnnotation != null) {
deselectAnnotation();
// deselect any selected marker
if (mSelectedMarker != null) {
deselectMarker();
}

// notify app of map click
Expand Down
Loading

0 comments on commit 576488f

Please sign in to comment.