diff options
author | Tobrun <tobrun.van.nuland@gmail.com> | 2016-12-14 22:09:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-14 22:09:30 +0100 |
commit | 05c693555606d9184f0cb7cc24129353800dd21f (patch) | |
tree | 17372a24a055f3b6a8279d434f6d0f22d3f03fd9 /platform | |
parent | f74de6731591ef11a75612b31f62877deb9f833c (diff) | |
download | qtlocation-mapboxgl-05c693555606d9184f0cb7cc24129353800dd21f.tar.gz |
[android] - add OnMarkerView add callback (#7429)
Diffstat (limited to 'platform')
6 files changed, 182 insertions, 70 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java index f462c00f98..8989bb22d7 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java @@ -6,6 +6,7 @@ import android.graphics.RectF; import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.util.LongSparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -13,6 +14,7 @@ import android.widget.ImageView; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.constants.MapboxConstants; +import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.utils.AnimatorUtils; @@ -28,10 +30,11 @@ import java.util.Map; * This class is responsible for managing a {@link MarkerView} item. * </p> */ -public class MarkerViewManager { +public class MarkerViewManager implements MapView.OnMapChangedListener { private final ViewGroup markerViewContainer; private final Map<MarkerView, View> markerViewMap = new HashMap<>(); + private final LongSparseArray<OnMarkerViewAddedListener> markerViewAddedListenerMap = new LongSparseArray<>(); private final List<MapboxMap.MarkerViewAdapter> markerViewAdapters = new ArrayList<>(); // TODO refactor MapboxMap out for Projection and Transform @@ -40,6 +43,7 @@ public class MarkerViewManager { private long viewMarkerBoundsUpdateTime; private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener; + private boolean isWaitingForRenderInvoke; /** * Creates an instance of MarkerViewManager. @@ -57,6 +61,19 @@ public class MarkerViewManager { this.mapboxMap = mapboxMap; } + + @Override + public void onMapChanged(@MapView.MapChange int change) { + if (isWaitingForRenderInvoke && change == MapView.DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) { + isWaitingForRenderInvoke = false; + invalidateViewMarkersInVisibleRegion(); + } + } + + public void setWaitingForRenderInvoke(boolean waitingForRenderInvoke) { + isWaitingForRenderInvoke = waitingForRenderInvoke; + } + /** * Animate a MarkerView to a given rotation. * <p> @@ -470,10 +487,21 @@ public class MarkerViewManager { markerViewContainer.addView(adaptedView); } } + + // notify listener is marker view is rendered + OnMarkerViewAddedListener onViewAddedListener = markerViewAddedListenerMap.get(marker.getId()); + if (onViewAddedListener != null) { + onViewAddedListener.onViewAdded(marker); + markerViewAddedListenerMap.remove(marker.getId()); + } } } } } + + // clear map, don't keep references to MarkerView listeners that are not found in the bounds of the map. + markerViewAddedListenerMap.clear(); + // trigger update to make newly added ViewMarker visible, // these would only be updated when the map is moved. update(); @@ -555,6 +583,10 @@ public class MarkerViewManager { return markerViewContainer; } + public void addOnMarkerViewAddedListener(MarkerView markerView, OnMarkerViewAddedListener onMarkerViewAddedListener) { + markerViewAddedListenerMap.put(markerView.getId(), onMarkerViewAddedListener); + } + /** * Default MarkerViewAdapter used for base class of {@link MarkerView} to adapt a MarkerView to * an ImageView. @@ -588,4 +620,21 @@ public class MarkerViewManager { ImageView imageView; } } + + /** + * Interface definition invoked when the View of a MarkerView has been added to the map. + * <p> + * {@link MapboxMap#addMarker(BaseMarkerOptions)} + * and only when the related MarkerView is found in the viewport of the map. + * </p> + */ + public interface OnMarkerViewAddedListener { + + /** + * Invoked when the View of a MarkerView has been added to the Map. + * + * @param markerView The MarkerView the View was added for + */ + void onViewAdded(@NonNull MarkerView markerView); + } } 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 40f4ff118e..eb90ae764b 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 @@ -20,6 +20,7 @@ import com.mapbox.mapboxsdk.annotations.PolylineOptions; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; /** @@ -32,7 +33,7 @@ import java.util.List; * Exposes convenience methods to add/remove/update all subtypes of annotations found in com.mapbox.mapboxsdk.annotations. * </p> */ -class AnnotationManager implements MapView.OnMapChangedListener { +class AnnotationManager { private final NativeMapView nativeMapView; private final MapView mapView; @@ -44,8 +45,8 @@ class AnnotationManager implements MapView.OnMapChangedListener { private MapboxMap mapboxMap; + private HashMap<MarkerView, MarkerViewManager.OnMarkerViewAddedListener> markerMap = new HashMap<>(); private MapboxMap.OnMarkerClickListener onMarkerClickListener; - private boolean isWaitingForRenderInvoke; AnnotationManager(NativeMapView view, MapView mapView, MarkerViewManager markerViewManager) { this.nativeMapView = view; @@ -54,7 +55,7 @@ class AnnotationManager implements MapView.OnMapChangedListener { this.markerViewManager = markerViewManager; if (view != null) { // null checking needed for unit tests - view.addOnMapChangedListener(this); + nativeMapView.addOnMapChangedListener(markerViewManager); } } @@ -66,14 +67,6 @@ class AnnotationManager implements MapView.OnMapChangedListener { return this; } - @Override - public void onMapChanged(@MapView.MapChange int change) { - if (isWaitingForRenderInvoke && change == MapView.DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) { - isWaitingForRenderInvoke = false; - markerViewManager.invalidateViewMarkersInVisibleRegion(); - } - } - // // Annotations // @@ -218,7 +211,6 @@ class AnnotationManager implements MapView.OnMapChangedListener { } MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, @NonNull MapboxMap mapboxMap) { - isWaitingForRenderInvoke = true; MarkerView marker = prepareViewMarker(markerOptions); marker.setMapboxMap(mapboxMap); long id = nativeMapView.addMarker(marker); @@ -227,13 +219,28 @@ class AnnotationManager implements MapView.OnMapChangedListener { return marker; } + public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, @NonNull MapboxMap mapboxMap, final MarkerViewManager.OnMarkerViewAddedListener onMarkerViewAddedListener) { + final MarkerView marker = prepareViewMarker(markerOptions); + + // add marker to map + marker.setMapboxMap(mapboxMap); + long id = nativeMapView.addMarker(marker); + marker.setId(id); + annotations.put(id, marker); + + markerViewManager.addOnMarkerViewAddedListener(marker, onMarkerViewAddedListener); + markerViewManager.setWaitingForRenderInvoke(true); + return marker; + } + + List<MarkerView> addMarkerViews(@NonNull List<? extends BaseMarkerViewOptions> markerViewOptions, @NonNull MapboxMap mapboxMap) { List<MarkerView> markers = new ArrayList<>(); for (BaseMarkerViewOptions markerViewOption : markerViewOptions) { // if last marker if (markerViewOptions.indexOf(markerViewOption) == markerViewOptions.size() - 1) { // get notified when render occurs to invalidate and draw MarkerViews - isWaitingForRenderInvoke = true; + markerViewManager.setWaitingForRenderInvoke(true); } // add marker to map MarkerView marker = prepareViewMarker(markerViewOption); 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 6820e3d08f..924ea0d190 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 @@ -905,7 +905,25 @@ public final class MapboxMap { @UiThread @NonNull public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions) { - return annotationManager.addMarker(markerOptions, this); + return annotationManager.addMarker(markerOptions, this, null); + } + + + /** + * <p> + * Adds a marker to this map. + * </p> + * The marker's icon is rendered on the map at the location {@code Marker.position}. + * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. + * + * @param markerOptions A marker options object that defines how to render the marker. + * @param onMarkerViewAddedListener Callback invoked when the View has been added to the map. + * @return The {@code Marker} that was added to the map. + */ + @UiThread + @NonNull + public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, final MarkerViewManager.OnMarkerViewAddedListener onMarkerViewAddedListener) { + return annotationManager.addMarker(markerOptions, this, onMarkerViewAddedListener); } @UiThread diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java index b732d5a066..397ac1d0c9 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java @@ -18,6 +18,7 @@ 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.annotations.MarkerViewManager; import com.mapbox.mapboxsdk.annotations.MarkerViewOptions; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.geometry.LatLng; @@ -61,23 +62,25 @@ public class AnimatedMarkerActivity extends AppCompatActivity { public void onMapReady(@NonNull final MapboxMap mapboxMap) { AnimatedMarkerActivity.this.mapboxMap = mapboxMap; setupMap(); - - for (int i = 0; i < 10; i++) { - addRandomCar(); - } - - addPassenger(); - addMainCar(); - animateMoveToPassenger(carMarker); + mapView.post(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 10; i++) { + addRandomCar(); + } + addPassenger(); + addMainCar(); + } + }); } }); } private void setupMap() { CameraPosition cameraPosition = new CameraPosition.Builder() - .target(dupontCircle) - .zoom(15) - .build(); + .target(dupontCircle) + .zoom(15) + .build(); mapboxMap.setCameraPosition(cameraPosition); } @@ -86,10 +89,10 @@ public class AnimatedMarkerActivity extends AppCompatActivity { if (passengerMarker == null) { Icon icon = IconFactory.getInstance(AnimatedMarkerActivity.this) - .fromResource(R.drawable.ic_directions_run_black_24dp); + .fromResource(R.drawable.ic_directions_run_black_24dp); passengerMarker = mapboxMap.addMarker(new MarkerViewOptions() - .position(randomLatLng) - .icon(icon)); + .position(randomLatLng) + .icon(icon)); } else { passengerMarker.setPosition(randomLatLng); } @@ -99,13 +102,18 @@ public class AnimatedMarkerActivity extends AppCompatActivity { LatLng randomLatLng = getLatLngInBounds(); if (carMarker == null) { - carMarker = createCarMarker(randomLatLng, R.drawable.ic_taxi_top); + carMarker = createCarMarker(randomLatLng, R.drawable.ic_taxi_top, new MarkerViewManager.OnMarkerViewAddedListener() { + @Override + public void onViewAdded(@NonNull MarkerView markerView) { + // Make sure the car marker is selected so that it's always brought to the front (#5285) + mapboxMap.selectMarker(carMarker); + animateMoveToPassenger(carMarker); + } + }); + } else { carMarker.setPosition(randomLatLng); } - - // Make sure the car marker is selected so that it's always brought to the front (#5285) - mapboxMap.selectMarker(carMarker); } private void animateMoveToPassenger(final MarkerView car) { @@ -120,8 +128,12 @@ public class AnimatedMarkerActivity extends AppCompatActivity { } protected void addRandomCar() { - MarkerView car = createCarMarker(getLatLngInBounds(), R.drawable.ic_car_top); - randomlyMoveMarker(car); + createCarMarker(getLatLngInBounds(), R.drawable.ic_car_top, new MarkerViewManager.OnMarkerViewAddedListener() { + @Override + public void onViewAdded(@NonNull MarkerView markerView) { + randomlyMoveMarker(markerView); + } + }); } private void randomlyMoveMarker(final MarkerView marker) { @@ -140,7 +152,7 @@ public class AnimatedMarkerActivity extends AppCompatActivity { marker.setRotation((float) getBearing(marker.getPosition(), to)); final ValueAnimator markerAnimator = ObjectAnimator.ofObject( - marker, "position", new LatLngEvaluator(), marker.getPosition(), to); + marker, "position", new LatLngEvaluator(), marker.getPosition(), to); markerAnimator.setDuration((long) (10 * marker.getPosition().distanceTo(to))); markerAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); @@ -150,14 +162,14 @@ public class AnimatedMarkerActivity extends AppCompatActivity { return markerAnimator; } - private MarkerView createCarMarker(LatLng start, @DrawableRes int carResource) { + private MarkerView createCarMarker(LatLng start, @DrawableRes int carResource, MarkerViewManager.OnMarkerViewAddedListener listener) { Icon icon = IconFactory.getInstance(AnimatedMarkerActivity.this) - .fromResource(carResource); + .fromResource(carResource); //View Markers return mapboxMap.addMarker(new MarkerViewOptions() - .position(start) - .icon(icon)); + .position(start) + .icon(icon), listener); //GL Markers // return mapboxMap.addMarker(new MarkerOptions() @@ -170,9 +182,9 @@ public class AnimatedMarkerActivity extends AppCompatActivity { LatLngBounds bounds = mapboxMap.getProjection().getVisibleRegion().latLngBounds; Random generator = new Random(); double randomLat = bounds.getLatSouth() + generator.nextDouble() - * (bounds.getLatNorth() - bounds.getLatSouth()); + * (bounds.getLatNorth() - bounds.getLatSouth()); double randomLon = bounds.getLonWest() + generator.nextDouble() - * (bounds.getLonEast() - bounds.getLonWest()); + * (bounds.getLonEast() - bounds.getLonWest()); return new LatLng(randomLat, randomLon); } @@ -239,9 +251,9 @@ public class AnimatedMarkerActivity extends AppCompatActivity { @Override public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) { latLng.setLatitude(startValue.getLatitude() - + ((endValue.getLatitude() - startValue.getLatitude()) * fraction)); + + ((endValue.getLatitude() - startValue.getLatitude()) * fraction)); latLng.setLongitude(startValue.getLongitude() - + ((endValue.getLongitude() - startValue.getLongitude()) * fraction)); + + ((endValue.getLongitude() - startValue.getLongitude()) * fraction)); return latLng; } } @@ -256,7 +268,7 @@ public class AnimatedMarkerActivity extends AppCompatActivity { double lat2 = degrees2radians * to.getLatitude(); double a = Math.sin(lon2 - lon1) * Math.cos(lat2); double b = Math.cos(lat1) * Math.sin(lat2) - - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1); + - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1); return radians2degrees * Math.atan2(a, b); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewScaleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewScaleActivity.java index befa63cca0..762117ae7f 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewScaleActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewScaleActivity.java @@ -8,10 +8,12 @@ import android.view.MenuItem; import android.view.View; import android.widget.SeekBar; import android.widget.TextView; +import android.widget.Toast; import com.mapbox.mapboxsdk.annotations.Icon; import com.mapbox.mapboxsdk.annotations.IconFactory; import com.mapbox.mapboxsdk.annotations.MarkerView; +import com.mapbox.mapboxsdk.annotations.MarkerViewManager; import com.mapbox.mapboxsdk.annotations.MarkerViewOptions; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.maps.MapView; @@ -25,7 +27,9 @@ public class MarkerViewScaleActivity extends AppCompatActivity implements OnMapR private MapboxMap mapboxMap; private MapView mapView; - private View markerView; + + private MarkerView markerView; + private MarkerViewManager markerViewManager; @Override protected void onCreate(Bundle savedInstanceState) { @@ -41,10 +45,6 @@ public class MarkerViewScaleActivity extends AppCompatActivity implements OnMapR actionBar.setDisplayShowHomeEnabled(true); } - final SeekBar xBar = (SeekBar) findViewById(R.id.seekbar_factor); - TextView textView = (TextView) findViewById(R.id.textview_factor); - xBar.setOnSeekBarChangeListener(new FactorChangeListener(textView)); - mapView = (MapView) findViewById(R.id.mapView); mapView.onCreate(savedInstanceState); mapView.getMapAsync(this); @@ -53,17 +53,40 @@ public class MarkerViewScaleActivity extends AppCompatActivity implements OnMapR @Override public void onMapReady(MapboxMap map) { mapboxMap = map; + markerViewManager = map.getMarkerViewManager(); + + final SeekBar xBar = (SeekBar) findViewById(R.id.seekbar_factor); + final TextView textView = (TextView) findViewById(R.id.textview_factor); + + // We need to listen to a render event to be sure + // the View of the Marker has been added to the map + mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() { + @Override + public void onMapChanged(@MapView.MapChange int change) { + if (isMarkerRendered()) { + Toast.makeText(MarkerViewScaleActivity.this, "MarkerView is ready", Toast.LENGTH_SHORT).show(); + View view = markerViewManager.getView(markerView); + xBar.setOnSeekBarChangeListener(new FactorChangeListener(view, textView)); + xBar.setClickable(true); + mapView.removeOnMapChangedListener(this); + } + } + + private boolean isMarkerRendered() { + return markerView != null && markerViewManager.getView(markerView) != null; + } + }); + Icon icon = IconFactory.getInstance(MarkerViewScaleActivity.this) .fromResource(R.drawable.ic_circle); - MarkerView marker = mapboxMap.addMarker(new MarkerViewOptions() + markerView = mapboxMap.addMarker(new MarkerViewOptions() .position(new LatLng(38.907192, -77.036871)) .icon(icon) .flat(true)); - - markerView = mapboxMap.getMarkerViewManager().getView(marker); } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -76,30 +99,30 @@ public class MarkerViewScaleActivity extends AppCompatActivity implements OnMapR } @Override - protected void onStart() { - super.onStart(); - mapView.onStart(); - } - - @Override - protected void onResume() { + public void onResume() { super.onResume(); mapView.onResume(); } @Override - protected void onPause() { - super.onPause(); - mapView.onPause(); + public void onStart() { + super.onResume(); + mapView.onStart(); } @Override - protected void onStop() { + public void onStop(){ super.onStop(); mapView.onStop(); } @Override + public void onPause() { + super.onPause(); + mapView.onPause(); + } + + @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); @@ -117,11 +140,13 @@ public class MarkerViewScaleActivity extends AppCompatActivity implements OnMapR mapView.onLowMemory(); } - private class FactorChangeListener implements SeekBar.OnSeekBarChangeListener { + private static class FactorChangeListener implements SeekBar.OnSeekBarChangeListener { private TextView textView; + private View view; - public FactorChangeListener(TextView textView) { + FactorChangeListener(View view, TextView textView) { + this.view = view; this.textView = textView; } @@ -129,9 +154,9 @@ public class MarkerViewScaleActivity extends AppCompatActivity implements OnMapR public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float newScale = getScale(progress); textView.setText(String.format(Locale.US, "Scale: %.1f", newScale)); - if (MarkerViewScaleActivity.this.markerView != null) { - markerView.setScaleX(newScale); - markerView.setScaleY(newScale); + if (view != null) { + view.setScaleX(newScale); + view.setScaleY(newScale); } } @@ -151,4 +176,4 @@ public class MarkerViewScaleActivity extends AppCompatActivity implements OnMapR } } -} +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_scale.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_scale.xml index afa769d58d..8f98b5bea2 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_scale.xml +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view_scale.xml @@ -39,6 +39,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/title" + android:clickable="false" android:layout_marginLeft="56dp" android:progress="0" /> |