summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorTobrun Van Nuland <tobrun.van.nuland@gmail.com>2016-06-03 14:29:20 +0200
committerTobrun <tobrun.van.nuland@gmail.com>2016-06-05 14:23:24 +0200
commit436c23c40b37c4863ddfbc25c6463ae2f2767a06 (patch)
treef5f78cd7d9deaaa8e16be10a8480e73f5f93b977 /platform
parent4094987fa09561c4c69b1b4cf8a6cbf9d3dd0433 (diff)
downloadqtlocation-mapboxgl-436c23c40b37c4863ddfbc25c6463ae2f2767a06.tar.gz
[android] #5171 - introduce new select/deselect animation system for view markers
Diffstat (limited to 'platform')
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java57
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java99
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java67
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java56
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java172
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java18
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java91
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java17
11 files changed, 414 insertions, 167 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java
index 0cd54fc0f0..57e6adb86d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java
@@ -30,6 +30,7 @@ public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends Base
protected int deselectAnimRes;
protected int rotation;
protected boolean visible = true;
+ protected boolean selected;
/**
* Default constructor
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
index d0e47110f4..877a4e62d6 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
@@ -1,7 +1,9 @@
package com.mapbox.mapboxsdk.annotations;
import android.graphics.Bitmap;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.view.View;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -31,15 +33,14 @@ public class MarkerView extends Marker {
private boolean flat;
private boolean visible = true;
- private int selectAnimRes;
- private int deselectAnimRes;
-
private float tiltValue;
private float rotation;
private float alpha = 1;
private Icon markerViewIcon;
+ private boolean selected;
+
/**
* Publicly hidden default constructor
*/
@@ -58,12 +59,11 @@ public class MarkerView extends Marker {
this.infoWindowAnchorU = baseMarkerViewOptions.getInfoWindowAnchorU();
this.infoWindowAnchorV = baseMarkerViewOptions.getInfoWindowAnchorV();
this.flat = baseMarkerViewOptions.isFlat();
- this.selectAnimRes = baseMarkerViewOptions.getSelectAnimRes();
- this.deselectAnimRes = baseMarkerViewOptions.getDeselectAnimRes();
this.infoWindowAnchorU = baseMarkerViewOptions.infoWindowAnchorU;
this.infoWindowAnchorV = baseMarkerViewOptions.infoWindowAnchorV;
this.anchorU = baseMarkerViewOptions.anchorU;
this.anchorV = baseMarkerViewOptions.anchorV;
+ this.selected = baseMarkerViewOptions.selected;
}
/**
@@ -196,42 +196,6 @@ public class MarkerView extends Marker {
}
/**
- * Get the animator resource used to animate to the selected state of a MarkerView.
- *
- * @return the animator resource used
- */
- public int getSelectAnimRes() {
- return selectAnimRes;
- }
-
- /**
- * Set the animator resource used to animate to the deselected state of a MarkerView.
- *
- * @param selectAnimRes the animator resource used
- */
- public void setSelectAnimRes(int selectAnimRes) {
- this.selectAnimRes = selectAnimRes;
- }
-
- /**
- * Get the animator resource used to animate to the deslected state of a MarkerView.
- *
- * @return the animator resource used
- */
- public int getDeselectAnimRes() {
- return deselectAnimRes;
- }
-
- /**
- * Set the animator resource used to animate to the selected state of a MarkerView.
- *
- * @param deselectAnimRes the animator resource used
- */
- public void setDeselectAnimRes(int deselectAnimRes) {
- this.deselectAnimRes = deselectAnimRes;
- }
-
- /**
* Internal method to get the current tilted value of a MarkerView.
*
* @return the tilted value
@@ -338,6 +302,17 @@ public class MarkerView extends Marker {
super.setIcon(transparentIcon);
}
+ public boolean isSelected() {
+ return selected;
+ }
+
+ /**
+ * For internal use only, use {@link MapboxMap#selectMarker(Marker)} instead.
+ */
+ void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
/**
* Get the icon of the MarkerView.
*
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 39e17fd683..c8ecb3eb14 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
@@ -51,7 +51,6 @@ public class MarkerViewManager {
this.mapView = mapView;
this.markerViewMap = new HashMap<>();
this.defaultMarkerViewAdapter = new ImageMarkerViewAdapter(mapView.getContext());
- // FIXME only add this if a MarkerView instance is added to MapboxMap
this.markerViewAdapters.add(defaultMarkerViewAdapter);
}
@@ -166,8 +165,7 @@ public class MarkerViewManager {
/**
* Animate a MarkerView to a deselected state.
* <p>
- * The {@link MarkerView#getDeselectAnimRes()} will be called to get the related animation.
- * If non are provided, no animation will be started.
+ * The {@link ImageMarkerViewAdapter#onDeselect(MarkerView, View)} will be called to execute an animation.
* </p>
*
* @param marker the MarkerView to deselect
@@ -175,10 +173,29 @@ public class MarkerViewManager {
public void deselect(@NonNull MarkerView marker) {
final View convertView = markerViewMap.get(marker);
if (convertView != null) {
- int deselectAnimatorRes = marker.getDeselectAnimRes();
- if (deselectAnimatorRes != 0) {
- AnimatorUtils.animate(convertView, deselectAnimatorRes);
+ for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
+ adapter.onDeselect(marker, convertView);
+ }
+ }
+ }
+ }
+
+ public void select(@NonNull MarkerView marker) {
+ final View convertView = markerViewMap.get(marker);
+ for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
+ select(marker, convertView, adapter);
+ }
+ }
+ }
+
+ public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter) {
+ if (convertView != null) {
+ if (adapter.onSelect(marker, convertView, false)) {
+ mapboxMap.selectMarker(marker);
}
+ marker.setSelected(true);
}
}
@@ -191,42 +208,35 @@ public class MarkerViewManager {
* the {@link MarkerView} from the underlying collection if needed.
* </p>
*
- * @param marker the MarkerView to remove
- * @param removeFromMap flag indicating if a MarkerView will be removed from the collection.
+ * @param marker the MarkerView to remove
*/
- public void removeMarkerView(MarkerView marker, boolean removeFromMap) {
+ public void removeMarkerView(MarkerView marker) {
final View viewHolder = markerViewMap.get(marker);
if (viewHolder != null && marker != null) {
for (final MapboxMap.MarkerViewAdapter<?> adapter : markerViewAdapters) {
- if (adapter.getMarkerClass() == marker.getClass()) {
-
- // get pool of Views associated to an adapter
- final Pools.SimplePool<View> viewPool = adapter.getViewReusePool();
-
- // cancel ongoing animations
- viewHolder.animate().cancel();
- viewHolder.setAlpha(1);
- AnimatorUtils.alpha(viewHolder, 0, new AnimatorUtils.OnAnimationEndListener() {
- @Override
- public void onAnimationEnd() {
- viewHolder.setVisibility(View.GONE);
- viewPool.release(viewHolder);
- }
- });
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
+ if (adapter.prepareViewForReuse(marker, viewHolder)) {
+ adapter.releaseView(viewHolder);
+ }
}
}
}
- if (removeFromMap) {
- markerViewMap.remove(marker);
- }
+ markerViewMap.remove(marker);
}
/**
- * Add a MarkerViewAdapter.
+ * Add a MarkerViewAdapter to the MarkerViewManager.
+ * <p>
+ * The provided MarkerViewAdapter must use supply a generic subclass of MarkerView.
+ * </p>
*
* @param markerViewAdapter the MarkerViewAdapter to add
*/
- public void addMarkerViewAdapter(@Nullable MapboxMap.MarkerViewAdapter markerViewAdapter) {
+ public void addMarkerViewAdapter(MapboxMap.MarkerViewAdapter markerViewAdapter) {
+ if (markerViewAdapter.getMarkerClass().equals(MarkerView.class)) {
+ throw new RuntimeException("Providing a custom MarkerViewAdapter requires subclassing MarkerView");
+ }
+
if (!markerViewAdapters.contains(markerViewAdapter)) {
markerViewAdapters.add(markerViewAdapter);
invalidateViewMarkersInBounds();
@@ -288,12 +298,13 @@ public class MarkerViewManager {
if (!markers.contains(m)) {
// remove marker
convertView = markerViewMap.get(m);
- int deselectAnimRes = m.getDeselectAnimRes();
- if (deselectAnimRes != 0) {
- AnimatorUtils.animate(convertView, deselectAnimRes, 0);
+ for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass().equals(m.getClass())) {
+ adapter.prepareViewForReuse(m, convertView);
+ adapter.releaseView(convertView);
+ iterator.remove();
+ }
}
- removeMarkerView(m, false);
- iterator.remove();
}
}
@@ -301,7 +312,7 @@ public class MarkerViewManager {
for (final MarkerView marker : markers) {
if (!markerViewMap.containsKey(marker)) {
for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
- if (adapter.getMarkerClass() == marker.getClass()) {
+ if (adapter.getMarkerClass().equals(marker.getClass())) {
convertView = (View) adapter.getViewReusePool().acquire();
final View adaptedView = adapter.getView(marker, convertView, mapView);
if (adaptedView != null) {
@@ -321,13 +332,11 @@ public class MarkerViewManager {
if (mapboxMap.getSelectedMarkers().contains(marker)) {
// if a marker to be shown was selected
// replay that animation with duration 0
- int selectAnimRes = marker.getSelectAnimRes();
- if (selectAnimRes != 0) {
- AnimatorUtils.animate(convertView, selectAnimRes, 0);
+ if (adapter.onSelect(marker, adaptedView, true)) {
+ mapboxMap.selectMarker(marker);
}
}
- final int animSelectRes = marker.getSelectAnimRes();
adaptedView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
@@ -342,17 +351,7 @@ public class MarkerViewManager {
int infoWindowOffsetY = (int) ((adaptedView.getHeight() * marker.getInfoWindowAnchorV()) - marker.getOffsetY());
marker.setTopOffsetPixels(infoWindowOffsetY);
marker.setRightOffsetPixels(infoWindowOffsetX);
-
- if (animSelectRes != 0) {
- AnimatorUtils.animate(v, animSelectRes, new AnimatorUtils.OnAnimationEndListener() {
- @Override
- public void onAnimationEnd() {
- mapboxMap.selectMarker(marker);
- }
- });
- } else {
- mapboxMap.selectMarker(marker);
- }
+ select(marker, v, adapter);
}
}
});
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java
index 0c9faed355..ebf98173c1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java
@@ -82,8 +82,6 @@ public class MarkerViewOptions extends BaseMarkerViewOptions<MarkerView, MarkerV
marker.setFlat(flat);
marker.setAnchor(anchorU, anchorV);
marker.setInfoWindowAnchor(infoWindowAnchorU, infoWindowAnchorV);
- marker.setSelectAnimRes(selectAnimRes);
- marker.setDeselectAnimRes(deselectAnimRes);
marker.setRotation(rotation);
marker.setVisible(visible);
return marker;
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 81b56cbd4c..bc0924c4f3 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
@@ -951,7 +951,7 @@ public class MapboxMap {
Marker marker = (Marker) annotation;
marker.hideInfoWindow();
if (marker instanceof MarkerView) {
- mMarkerViewManager.removeMarkerView((MarkerView) marker, true);
+ mMarkerViewManager.removeMarkerView((MarkerView) marker);
}
}
long id = annotation.getId();
@@ -985,7 +985,7 @@ public class MapboxMap {
Marker marker = (Marker) annotation;
marker.hideInfoWindow();
if (marker instanceof MarkerView) {
- mMarkerViewManager.removeMarkerView((MarkerView) marker, true);
+ mMarkerViewManager.removeMarkerView((MarkerView) marker);
}
}
ids[i] = annotationList.get(i).getId();
@@ -1011,7 +1011,7 @@ public class MapboxMap {
Marker marker = (Marker) annotation;
marker.hideInfoWindow();
if (marker instanceof MarkerView) {
- mMarkerViewManager.removeMarkerView((MarkerView) marker, true);
+ mMarkerViewManager.removeMarkerView((MarkerView) marker);
}
}
}
@@ -1841,11 +1841,56 @@ public class MapboxMap {
public abstract View getView(@NonNull U marker, @NonNull View convertView, @NonNull ViewGroup parent);
/**
+ * Called when an MarkerView is removed from the MapView or the View object is going to be reused.
+ * <p>
+ * <p>
+ * This method should be used to reset an animated view back to it's original state for view reuse.
+ * </p>
+ * <p>
+ * Returning true indicates you want to the view reuse to be handled automatically.
+ * Returning false indicates you want to perform an animation and you are required calling {@link #releaseView(View)} yourself.
+ * </p>
+ *
+ * @param marker the model representing the MarkerView
+ * @param convertView the reusable view
+ * @return true if you want reuse to occur automatically, false if you want to manage this yourself.
+ */
+ public boolean prepareViewForReuse(@NonNull MarkerView marker, @NonNull View convertView) {
+ return true;
+ }
+
+ /**
+ * Called when a MarkerView is selected from the MapView.
+ * <p>
+ * Returning true from this method indicates you want to move the MarkerView to the selected state.
+ * Returning false indicates you want to animate the View first an manually select the MarkerView when appropriate.
+ * </p>
+ *
+ * @param marker the model representing the MarkerView
+ * @param convertView the reusable view
+ * @param reselectionFromRecycling indicates if the onSelect callback is the initial selection
+ * callback or that selection occurs due to recreation of selected marker
+ * @return true if you want to select the Marker immediately, false if you want to manage this yourself.
+ */
+ public boolean onSelect(@NonNull U marker, @NonNull View convertView, boolean reselectionFromRecycling) {
+ return true;
+ }
+
+ /**
+ * Called when a MarkerView is deselected from the MapView.
+ *
+ * @param marker the model representing the MarkerView
+ * @param convertView the reusable view
+ */
+ public void onDeselect(@NonNull U marker, @NonNull View convertView) {
+ }
+
+ /**
* Returns the generic type of the used MarkerView.
*
* @return the generic type
*/
- public Class<U> getMarkerClass() {
+ public final Class<U> getMarkerClass() {
return persistentClass;
}
@@ -1854,7 +1899,7 @@ public class MapboxMap {
*
* @return the pool associated to this adapter
*/
- public Pools.SimplePool<View> getViewReusePool() {
+ public final Pools.SimplePool<View> getViewReusePool() {
return mViewReusePool;
}
@@ -1863,9 +1908,19 @@ public class MapboxMap {
*
* @return the context used
*/
- public Context getContext() {
+ public final Context getContext() {
return context;
}
+
+ /**
+ * Release a View to the ViewPool.
+ *
+ * @param view the view to be released
+ */
+ public final void releaseView(View view) {
+ view.setVisibility(View.GONE);
+ mViewReusePool.release(view);
+ }
}
/**
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
index 7a2241a84c..e4bf383c96 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
@@ -3,28 +3,28 @@ package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.ProgressDialog;
-import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
+import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
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.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
-import com.mapbox.mapboxsdk.annotations.MarkerView;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
@@ -86,36 +86,6 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
}
}
- public static class TextAdapter extends MapboxMap.MarkerViewAdapter<MarkerView> {
-
- private LayoutInflater inflater;
-
- public TextAdapter(@NonNull Context context) {
- super(context);
- this.inflater = LayoutInflater.from(context);
- }
-
- @Nullable
- @Override
- public View getView(@NonNull MarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
- ViewHolder viewHolder;
- if (convertView == null) {
- viewHolder = new ViewHolder();
- convertView = inflater.inflate(R.layout.view_text_marker, parent, false);
- viewHolder.title = (TextView) convertView.findViewById(R.id.textView);
- convertView.setTag(viewHolder);
- } else {
- viewHolder = (ViewHolder) convertView.getTag();
- }
- viewHolder.title.setText(marker.getTitle());
- return convertView;
- }
-
- private static class ViewHolder {
- TextView title;
- }
- }
-
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
int amount = Integer.valueOf(getResources().getStringArray(R.array.bulk_marker_list)[position]);
@@ -126,7 +96,6 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
}
}
-
private void onLatLngListLoaded(List<LatLng> latLngs, int amount) {
mLocations = latLngs;
showMarkers(amount);
@@ -140,26 +109,32 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
}
if (mCustomMarkerView) {
- showNativeMarkers(amount);
+ showViewMarkers(amount);
} else {
showGlMarkers(amount);
}
}
- private void showNativeMarkers(int amount) {
+ private void showViewMarkers(int amount) {
DecimalFormat formatter = new DecimalFormat("#.#####");
Random random = new Random();
int randomIndex;
+ Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_droppin_24dp, getTheme());
+ int redColor = ResourcesCompat.getColor(getResources(), android.R.color.holo_red_dark, getTheme());
+ drawable.setColorFilter(redColor, PorterDuff.Mode.SRC_IN);
+ Icon icon = IconFactory.getInstance(this).fromDrawable(drawable);
+
for (int i = 0; i < amount; i++) {
randomIndex = random.nextInt(mLocations.size());
LatLng latLng = mLocations.get(randomIndex);
mMapboxMap.addMarker(new MarkerViewOptions()
.position(latLng)
+ .icon(icon)
.title(String.valueOf(i))
.snippet(formatter.format(latLng.getLatitude()) + ", " + formatter.format(latLng.getLongitude())));
}
- }
+ }
private void showGlMarkers(int amount) {
List<MarkerOptions> markerOptionsList = new ArrayList<>();
@@ -247,9 +222,6 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView
showMarkers(amount);
}
- // add adapter
- mMapboxMap.getMarkerViewManager().addMarkerViewAdapter(new TextAdapter(BulkMarkerActivity.this));
-
mMapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
@Override
public void onMapChanged(@MapView.MapChange int change) {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
index 60ace581a4..93bed990fc 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
@@ -1,5 +1,9 @@
package com.mapbox.mapboxsdk.testapp.activity.annotation;
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -18,6 +22,8 @@ import android.widget.Toast;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
@@ -28,6 +34,8 @@ import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerOptions;
import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerView;
import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerViewOptions;
+import com.mapbox.mapboxsdk.testapp.model.annotations.TextMarkerView;
+import com.mapbox.mapboxsdk.testapp.model.annotations.TextMarkerViewOptions;
public class MarkerViewActivity extends AppCompatActivity {
@@ -35,13 +43,10 @@ public class MarkerViewActivity extends AppCompatActivity {
private MapView mMapView;
private final static LatLng[] LAT_LNGS = new LatLng[]{
- new LatLng(38.907327, -77.041293),
+ new LatLng(38.897424, -77.036508),
new LatLng(38.909698, -77.029642),
new LatLng(38.907227, -77.036530),
new LatLng(38.905607, -77.031916),
- new LatLng(38.897424, -77.036508),
- new LatLng(38.897642, -77.041980),
- new LatLng(38.889876, -77.008849),
new LatLng(38.889441, -77.050134)
};
@@ -83,24 +88,40 @@ public class MarkerViewActivity extends AppCompatActivity {
);
}
- // add child classes of ViewMarker
+ // add custom ViewMarker
CountryMarkerViewOptions options = new CountryMarkerViewOptions();
options.flagRes(R.drawable.icon_burned);
options.abbrevName("Mapbox");
+ options.title("Hello");
options.position(new LatLng(38.899774, -77.023237));
options.selectAnimatorResource(R.animator.rotate_360);
options.deselectAnimatorResource(R.animator.rotate_360);
options.flat(true);
mapboxMap.addMarker(options);
- // add default GL marker
- mMapboxMap.addMarker(new CountryMarkerOptions()
+ mMapboxMap.addMarker(new MarkerOptions()
.title("United States")
.position(new LatLng(38.902580, -77.050102))
);
+ mMapboxMap.addMarker(new TextMarkerViewOptions()
+ .text("A")
+ .position(new LatLng(38.889876, -77.008849))
+ );
+
+ mMapboxMap.addMarker(new TextMarkerViewOptions()
+ .text("B")
+ .position(new LatLng(38.907327, -77.041293))
+ );
+
+ mMapboxMap.addMarker(new TextMarkerViewOptions()
+ .text("C")
+ .position(new LatLng(38.897642, -77.041980))
+ );
+
// set adapters for child classes of ViewMarker
- markerViewManager.addMarkerViewAdapter(new CountryAdapter(MarkerViewActivity.this));
+ markerViewManager.addMarkerViewAdapter(new CountryAdapter(MarkerViewActivity.this, mapboxMap));
+ markerViewManager.addMarkerViewAdapter(new TextAdapter(MarkerViewActivity.this, mapboxMap));
// add a change listener to validate the size of amount of child views
mMapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
@@ -129,10 +150,12 @@ public class MarkerViewActivity extends AppCompatActivity {
private static class CountryAdapter extends MapboxMap.MarkerViewAdapter<CountryMarkerView> {
private LayoutInflater inflater;
+ private MapboxMap mapboxMap;
- public CountryAdapter(@NonNull Context context) {
+ public CountryAdapter(@NonNull Context context, @NonNull MapboxMap mapboxMap) {
super(context);
this.inflater = LayoutInflater.from(context);
+ this.mapboxMap = mapboxMap;
}
@Nullable
@@ -153,12 +176,143 @@ public class MarkerViewActivity extends AppCompatActivity {
return convertView;
}
+ @Override
+ public boolean onSelect(@NonNull final CountryMarkerView marker, @NonNull final View convertView, boolean reselectionForViewReuse) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ROTATION, 0, 360);
+ rotateAnimator.setDuration(reselectionForViewReuse ? 0 : 350);
+ rotateAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
+ mapboxMap.selectMarker(marker);
+ }
+ });
+ rotateAnimator.start();
+
+ // false indicates that we are calling selectMarker after our animation ourselves
+ // true will let the system call it for you, which will result in showing an InfoWindow instantly
+ return false;
+ }
+
+ @Override
+ public void onDeselect(@NonNull CountryMarkerView marker, @NonNull final View convertView) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ROTATION, 360, 0);
+ rotateAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ });
+ rotateAnimator.start();
+ }
+
private static class ViewHolder {
ImageView flag;
TextView abbrev;
}
}
+
+ private static class TextAdapter extends MapboxMap.MarkerViewAdapter<TextMarkerView> {
+
+ private LayoutInflater inflater;
+ private MapboxMap mapboxMap;
+
+ public TextAdapter(@NonNull Context context, @NonNull MapboxMap mapboxMap) {
+ super(context);
+ this.inflater = LayoutInflater.from(context);
+ this.mapboxMap = mapboxMap;
+ }
+
+ @Nullable
+ @Override
+ public View getView(@NonNull TextMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
+ ViewHolder viewHolder;
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ convertView = inflater.inflate(R.layout.view_text_marker, parent, false);
+ viewHolder.textView = (TextView) convertView.findViewById(R.id.textView);
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) convertView.getTag();
+ }
+ viewHolder.textView.setText(marker.getText());
+ return convertView;
+ }
+
+ @Override
+ public boolean onSelect(@NonNull final TextMarkerView marker, @NonNull final View convertView, boolean reselectionForViewReuse) {
+ animateGrow(marker, convertView, 0);
+
+ // false indicates that we are calling selectMarker after our animation ourselves
+ // true will let the system call it for you, which will result in showing an InfoWindow instantly
+ return false;
+ }
+
+ @Override
+ public void onDeselect(@NonNull TextMarkerView marker, @NonNull final View convertView) {
+ animateShrink(convertView, 350);
+ }
+
+ @Override
+ public boolean prepareViewForReuse(@NonNull MarkerView marker, @NonNull View convertView) {
+ // this method is called before a view will be reused, we need to restore view state
+ // as we have scaled the view in onSelect. If not correctly applied other MarkerView will
+ // become large since these have been recycled
+
+ // cancel ongoing animation
+ convertView.animate().cancel();
+
+ if (marker.isSelected()) {
+ // shrink view to be able to be reused
+ animateShrink(convertView, 0);
+ }
+
+ // true if you want reuse to occur automatically, false if you want to manage this yourself
+ return true;
+ }
+
+ private void animateGrow(@NonNull final MarkerView marker, @NonNull final View convertView, int duration) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ Animator animator = AnimatorInflater.loadAnimator(convertView.getContext(), R.animator.scale_up);
+ animator.setDuration(duration);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
+ mapboxMap.selectMarker(marker);
+ }
+ });
+ animator.setTarget(convertView);
+ animator.start();
+ }
+
+ private void animateShrink(@NonNull final View convertView, int duration) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ Animator animator = AnimatorInflater.loadAnimator(convertView.getContext(), R.animator.scale_down);
+ animator.setDuration(duration);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ });
+ animator.setTarget(convertView);
+ animator.start();
+ }
+
+ private static class ViewHolder {
+ TextView textView;
+ }
+ }
+
+
@Override
public void onResume() {
super.onResume();
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java
index c4ef4a8d13..ab0fd396ea 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java
@@ -64,6 +64,7 @@ public class CountryMarkerViewOptions extends BaseMarkerViewOptions<CountryMarke
out.writeInt(getSelectAnimRes());
out.writeInt(getDeselectAnimRes());
out.writeInt(getRotation());
+ out.writeByte((byte) (selected ? 1 :0));
Icon icon = getIcon();
out.writeByte((byte) (icon != null ? 1 : 0));
if (icon != null) {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java
new file mode 100644
index 0000000000..c0a589cb57
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java
@@ -0,0 +1,18 @@
+package com.mapbox.mapboxsdk.testapp.model.annotations;
+
+import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+
+public class TextMarkerView extends MarkerView {
+
+ private String text;
+
+ public TextMarkerView(BaseMarkerViewOptions baseMarkerViewOptions, String text) {
+ super(baseMarkerViewOptions);
+ this.text = text;
+ }
+
+ public String getText() {
+ return text;
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java
new file mode 100644
index 0000000000..48ab57345e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java
@@ -0,0 +1,91 @@
+package com.mapbox.mapboxsdk.testapp.model.annotations;
+
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
+import com.mapbox.mapboxsdk.annotations.Icon;
+import com.mapbox.mapboxsdk.annotations.IconFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+
+public class TextMarkerViewOptions extends BaseMarkerViewOptions<TextMarkerView,TextMarkerViewOptions> {
+
+ private String text;
+
+ public TextMarkerViewOptions() {
+ }
+
+ protected TextMarkerViewOptions(Parcel in) {
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ title(in.readString());
+ flat(in.readByte() != 0);
+ anchor(in.readFloat(), in.readFloat());
+ infoWindowAnchor(in.readFloat(), in.readFloat());
+ selectAnimatorResource(in.readInt());
+ deselectAnimatorResource(in.readInt());
+ rotation(in.readInt());
+ if (in.readByte() != 0) {
+ // this means we have an icon
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = IconFactory.recreate(iconId, iconBitmap);
+ icon(icon);
+ }
+ text(in.readString());
+ }
+
+ @Override
+ public TextMarkerViewOptions getThis() {
+ return this;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(getPosition(), flags);
+ out.writeString(getSnippet());
+ out.writeString(getTitle());
+ out.writeByte((byte) (isFlat() ? 1 : 0));
+ out.writeFloat(getAnchorU());
+ out.writeFloat(getAnchorV());
+ out.writeFloat(getInfoWindowAnchorU());
+ out.writeFloat(getInfoWindowAnchorV());
+ out.writeInt(getSelectAnimRes());
+ out.writeInt(getDeselectAnimRes());
+ out.writeInt(getRotation());
+ Icon icon = getIcon();
+ out.writeByte((byte) (icon != null ? 1 : 0));
+ if (icon != null) {
+ out.writeString(getIcon().getId());
+ out.writeParcelable(getIcon().getBitmap(), flags);
+ }
+ out.writeString(text);
+ }
+
+ @Override
+ public TextMarkerView getMarker() {
+ return new TextMarkerView(this, text);
+ }
+
+ public TextMarkerViewOptions text(String text) {
+ this.text = text;
+ return getThis();
+ }
+
+ public static final Parcelable.Creator<CountryMarkerViewOptions> CREATOR
+ = new Parcelable.Creator<CountryMarkerViewOptions>() {
+ public CountryMarkerViewOptions createFromParcel(Parcel in) {
+ return new CountryMarkerViewOptions(in);
+ }
+
+ public CountryMarkerViewOptions[] newArray(int size) {
+ return new CountryMarkerViewOptions[size];
+ }
+ };
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java
index 7d874f21fe..a4b3248f2e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java
@@ -3,7 +3,6 @@ package com.mapbox.mapboxsdk.annotations;
import android.os.Parcelable;
import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.utils.MockParcel;
import org.junit.Test;
@@ -98,22 +97,6 @@ public class MarkerViewTest {
}
@Test
- public void testSelectAnimRes() {
- int animatorRes = R.animator.rotate_360;
- MarkerViewOptions markerOptions = new MarkerViewOptions().selectAnimatorResource(animatorRes);
- MarkerView marker = markerOptions.getMarker();
- assertEquals("select animator resource should match ", animatorRes, marker.getSelectAnimRes(), 0);
- }
-
- @Test
- public void testDeselectAnimRes() {
- int animatorRes = R.animator.rotate_360;
- MarkerViewOptions markerOptions = new MarkerViewOptions().deselectAnimatorResource(animatorRes);
- MarkerView marker = markerOptions.getMarker();
- assertEquals("deselect animator resource should match ", animatorRes, marker.getDeselectAnimRes(), 0);
- }
-
- @Test
public void testRotation() {
int rotation = 90;
MarkerViewOptions markerOptions = new MarkerViewOptions().rotation(rotation);