From d7401f9e219e4607146cf1c34af23edb474348eb Mon Sep 17 00:00:00 2001 From: Tobrun Date: Tue, 18 Jul 2017 15:34:55 +0200 Subject: [android] - add OnPolygonClickListener and OnPolylineClickListener (#9443) --- .../mapbox/mapboxsdk/maps/AnnotationManager.java | 96 ++++++++++++++++++++-- .../java/com/mapbox/mapboxsdk/maps/MapboxMap.java | 50 +++++++++++ .../activity/annotation/PolygonActivity.java | 14 ++++ .../activity/annotation/PolylineActivity.java | 14 +++- 4 files changed, 164 insertions(+), 10 deletions(-) (limited to 'platform') 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 index 392eededdc..404cc5f3bd 100644 --- 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 @@ -9,6 +9,8 @@ import android.support.annotation.Nullable; import android.support.v4.util.LongSparseArray; import android.view.View; +import com.mapbox.mapboxsdk.Mapbox; +import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.annotations.Annotation; import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions; import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions; @@ -20,6 +22,7 @@ import com.mapbox.mapboxsdk.annotations.Polygon; import com.mapbox.mapboxsdk.annotations.PolygonOptions; import com.mapbox.mapboxsdk.annotations.Polyline; import com.mapbox.mapboxsdk.annotations.PolylineOptions; +import com.mapbox.services.commons.geojson.Feature; import java.util.ArrayList; import java.util.List; @@ -39,6 +42,8 @@ import timber.log.Timber; */ class AnnotationManager { + private static final String LAYER_ID_SHAPE_ANNOTATIONS = "com.mapbox.annotations.shape."; + private final NativeMapView nativeMapView; private final MapView mapView; private final IconManager iconManager; @@ -46,9 +51,12 @@ class AnnotationManager { private final MarkerViewManager markerViewManager; private final LongSparseArray annotations = new LongSparseArray<>(); private final List selectedMarkers = new ArrayList<>(); + private final List shapeAnnotationIds = new ArrayList<>(); private MapboxMap mapboxMap; private MapboxMap.OnMarkerClickListener onMarkerClickListener; + private MapboxMap.OnPolygonClickListener onPolygonClickListener; + private MapboxMap.OnPolylineClickListener onPolylineClickListener; AnnotationManager(NativeMapView view, MapView mapView, MarkerViewManager markerViewManager) { this.nativeMapView = view; @@ -101,6 +109,9 @@ class AnnotationManager { if (marker instanceof MarkerView) { markerViewManager.removeMarkerView((MarkerView) marker); } + } else { + // instanceOf Polygon/Polyline + shapeAnnotationIds.remove(annotation.getId()); } long id = annotation.getId(); if (nativeMapView != null) { @@ -131,6 +142,9 @@ class AnnotationManager { if (marker instanceof MarkerView) { markerViewManager.removeMarkerView((MarkerView) marker); } + } else { + // instanceOf Polygon/Polyline + shapeAnnotationIds.remove(annotation.getId()); } ids[i] = annotationList.get(i).getId(); } @@ -158,6 +172,9 @@ class AnnotationManager { if (marker instanceof MarkerView) { markerViewManager.removeMarkerView((MarkerView) marker); } + } else { + // instanceOf Polygon/Polyline + shapeAnnotationIds.remove(annotation.getId()); } } @@ -244,7 +261,6 @@ class AnnotationManager { return marker; } - List addMarkerViews(@NonNull List markerViewOptions, @NonNull MapboxMap mapboxMap) { List markers = new ArrayList<>(); @@ -278,7 +294,6 @@ class AnnotationManager { Timber.w("Attempting to update non-added Marker with value %s", updatedMarker); return; } - ensureIconLoaded(updatedMarker); nativeMapView.updateMarker(updatedMarker); annotations.setValueAt(annotations.indexOfKey(updatedMarker.getId()), updatedMarker); @@ -310,6 +325,14 @@ class AnnotationManager { onMarkerClickListener = listener; } + void setOnPolygonClickListener(@Nullable MapboxMap.OnPolygonClickListener listener) { + onPolygonClickListener = listener; + } + + void setOnPolylineClickListener(@Nullable MapboxMap.OnPolylineClickListener listener) { + onPolylineClickListener = listener; + } + void selectMarker(@NonNull Marker marker) { if (selectedMarkers.contains(marker)) { return; @@ -374,7 +397,7 @@ class AnnotationManager { @NonNull List getMarkersInRect(@NonNull RectF rectangle) { - // convert Rectangle to be density depedent + // convert Rectangle to be density dependent float pixelRatio = nativeMapView.getPixelRatio(); RectF rect = new RectF(rectangle.left / pixelRatio, rectangle.top / pixelRatio, @@ -438,6 +461,7 @@ class AnnotationManager { long id = nativeMapView != null ? nativeMapView.addPolygon(polygon) : 0; polygon.setId(id); polygon.setMapboxMap(mapboxMap); + shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + id); annotations.put(id, polygon); } return polygon; @@ -472,6 +496,7 @@ class AnnotationManager { id++; } polygon.setId(id); + shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + id); annotations.put(id, polygon); } } @@ -510,6 +535,7 @@ class AnnotationManager { long id = nativeMapView != null ? nativeMapView.addPolyline(polyline) : 0; polyline.setMapboxMap(mapboxMap); polyline.setId(id); + shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + id); annotations.put(id, polyline); } return polyline; @@ -546,6 +572,7 @@ class AnnotationManager { id++; } p.setId(id); + shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + id); annotations.put(id, p); } } @@ -555,6 +582,7 @@ class AnnotationManager { void updatePolyline(@NonNull Polyline polyline) { if (!isAddedToMap(polyline)) { Timber.w("Attempting to update non-added Polyline with value %s", polyline); + return; } nativeMapView.updatePolyline(polyline); @@ -619,11 +647,37 @@ class AnnotationManager { // boolean onTap(PointF tapPoint) { + ShapeAnnotationHit shapeAnnotationHit = getShapeAnnotationHitFromTap(tapPoint); + long shapeAnnotationId = new ShapeAnnotationHitResolver(mapboxMap).execute(shapeAnnotationHit); + if (shapeAnnotationId >= 0) { + handleClickForShapeAnnotation(shapeAnnotationId); + } + MarkerHit markerHit = getMarkerHitFromTouchArea(tapPoint); - long markerId = new MarkerHitResolver(markerViewManager, mapboxMap.getProjection()).execute(markerHit); + long markerId = new MarkerHitResolver(mapboxMap).execute(markerHit); return markerId >= 0 && isClickHandledForMarker(markerId); } + private ShapeAnnotationHit getShapeAnnotationHitFromTap(PointF tapPoint) { + float touchTargetSide = Mapbox.getApplicationContext().getResources().getDimension(R.dimen.mapbox_eight_dp); + RectF tapRect = new RectF( + tapPoint.x - touchTargetSide, + tapPoint.y - touchTargetSide, + tapPoint.x + touchTargetSide, + tapPoint.y + touchTargetSide + ); + return new ShapeAnnotationHit(tapRect, shapeAnnotationIds.toArray(new String[shapeAnnotationIds.size()])); + } + + private void handleClickForShapeAnnotation(long shapeAnnotationId) { + Annotation annotation = getAnnotation(shapeAnnotationId); + if (annotation instanceof Polygon && onPolygonClickListener != null) { + onPolygonClickListener.onPolygonClick((Polygon) annotation); + } else if (annotation instanceof Polyline && onPolylineClickListener != null) { + onPolylineClickListener.onPolylineClick((Polyline) annotation); + } + } + private MarkerHit getMarkerHitFromTouchArea(PointF tapPoint) { int averageIconWidthOffset = iconManager.getAverageIconWidth() / 2; int averageIconHeightOffset = iconManager.getAverageIconHeight() / 2; @@ -645,7 +699,7 @@ class AnnotationManager { } if (!handledDefaultClick) { - setMarkerSelectionState(marker); + toggleMarkerSelectionState(marker); } return true; } @@ -654,7 +708,7 @@ class AnnotationManager { return onMarkerClickListener != null && onMarkerClickListener.onMarkerClick(marker); } - private void setMarkerSelectionState(Marker marker) { + private void toggleMarkerSelectionState(Marker marker) { if (!selectedMarkers.contains(marker)) { selectMarker(marker); } else { @@ -662,6 +716,20 @@ class AnnotationManager { } } + private static class ShapeAnnotationHitResolver { + + private MapboxMap mapboxMap; + + ShapeAnnotationHitResolver(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + } + + public long execute(ShapeAnnotationHit shapeHit) { + List features = mapboxMap.queryRenderedFeatures(shapeHit.tapPoint, shapeHit.layerIds); + return features.isEmpty() ? -1 : Long.valueOf(features.get(0).getId()); + } + } + private static class MarkerHitResolver { private final MarkerViewManager markerViewManager; @@ -677,9 +745,9 @@ class AnnotationManager { private long closestMarkerId = -1; - MarkerHitResolver(@NonNull MarkerViewManager markerViewManager, @NonNull Projection projection) { - this.markerViewManager = markerViewManager; - this.projection = projection; + MarkerHitResolver(@NonNull MapboxMap mapboxMap) { + this.markerViewManager = mapboxMap.getMarkerViewManager(); + this.projection = mapboxMap.getProjection(); } public long execute(MarkerHit markerHit) { @@ -732,6 +800,16 @@ class AnnotationManager { } } + private static class ShapeAnnotationHit { + private final RectF tapPoint; + private final String[] layerIds; + + ShapeAnnotationHit(RectF tapRect, String[] layerIds) { + this.tapPoint = tapRect; + this.layerIds = layerIds; + } + } + private static class MarkerHit { private final RectF tapRect; private final List markers; 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 d672ab37c3..c8725d8d8d 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 @@ -1459,6 +1459,28 @@ public final class MapboxMap { annotationManager.setOnMarkerClickListener(listener); } + /** + * Sets a callback that's invoked when the user clicks on a polygon. + * + * @param listener The callback that's invoked when the user clicks on a polygon. + * To unset the callback, use null. + */ + @UiThread + public void setOnPolygonClickListener(@Nullable OnPolygonClickListener listener) { + annotationManager.setOnPolygonClickListener(listener); + } + + /** + * Sets a callback that's invoked when the user clicks on a polyline. + * + * @param listener The callback that's invoked when the user clicks on a polyline. + * To unset the callback, use null. + */ + @UiThread + public void setOnPolylineClickListener(@Nullable OnPolylineClickListener listener) { + annotationManager.setOnPolylineClickListener(listener); + } + /** *

* Selects a marker. The selected marker will have it's info window opened. @@ -2150,6 +2172,34 @@ public final class MapboxMap { boolean onMarkerClick(@NonNull Marker marker); } + /** + * Interface definition for a callback to be invoked when the user clicks on a polygon. + * + * @see MapboxMap#setOnPolygonClickListener(OnPolygonClickListener) + */ + public interface OnPolygonClickListener { + /** + * Called when the user clicks on a polygon. + * + * @param polygon The polygon the user clicked on. + */ + void onPolygonClick(@NonNull Polygon polygon); + } + + /** + * Interface definition for a callback to be invoked when the user clicks on a polyline. + * + * @see MapboxMap#setOnPolylineClickListener(OnPolylineClickListener) + */ + public interface OnPolylineClickListener { + /** + * Called when the user clicks on a polyline. + * + * @param polyline The polyline the user clicked on. + */ + void onPolylineClick(@NonNull Polyline polyline); + } + /** * Interface definition for a callback to be invoked when the user clicks on an info window. * diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java index b51d717f33..fecfe2a842 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java @@ -2,9 +2,11 @@ package com.mapbox.mapboxsdk.testapp.activity.annotation; import android.graphics.Color; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; +import android.widget.Toast; import com.mapbox.mapboxsdk.annotations.Polygon; import com.mapbox.mapboxsdk.annotations.PolygonOptions; @@ -77,6 +79,18 @@ public class PolygonActivity extends AppCompatActivity implements OnMapReadyCall @Override public void onMapReady(MapboxMap map) { mapboxMap = map; + + map.setOnPolygonClickListener(new MapboxMap.OnPolygonClickListener() { + @Override + public void onPolygonClick(@NonNull Polygon polygon) { + Toast.makeText( + PolygonActivity.this, + "You clicked on polygon with id = " + polygon.getId(), + Toast.LENGTH_SHORT + ).show(); + } + }); + polygon = mapboxMap.addPolygon(new PolygonOptions() .addAll(STAR_SHAPE_POINTS) .fillColor(BLUE_COLOR)); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java index 0aaa6127f4..b9dc39e5d4 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java @@ -67,8 +67,20 @@ public class PolylineActivity extends AppCompatActivity { mapView.onCreate(savedInstanceState); mapView.getMapAsync(new OnMapReadyCallback() { @Override - public void onMapReady(@NonNull MapboxMap mapboxMap) { + public void onMapReady(@NonNull final MapboxMap mapboxMap) { PolylineActivity.this.mapboxMap = mapboxMap; + + mapboxMap.setOnPolylineClickListener(new MapboxMap.OnPolylineClickListener() { + @Override + public void onPolylineClick(@NonNull Polyline polyline) { + Toast.makeText( + PolylineActivity.this, + "You clicked on polygon with id = " + polyline.getId(), + Toast.LENGTH_SHORT + ).show(); + } + }); + polylines = mapboxMap.addPolylines(polylineOptions); } }); -- cgit v1.2.1