[android] #3276 - View annotation integration in Marker
This commit is contained in:
@@ -18,6 +18,7 @@ public abstract class BaseMarkerOptions<U extends Marker, T extends BaseMarkerOp
|
||||
protected String snippet;
|
||||
protected String title;
|
||||
protected Icon icon;
|
||||
protected boolean markerView;
|
||||
|
||||
public T position(LatLng position) {
|
||||
this.position = position;
|
||||
@@ -39,8 +40,16 @@ public abstract class BaseMarkerOptions<U extends Marker, T extends BaseMarkerOp
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T markerView(boolean isMarkerView) {
|
||||
this.markerView = isMarkerView;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public abstract T getThis();
|
||||
|
||||
public abstract U getMarker();
|
||||
|
||||
public boolean isViewMarker() {
|
||||
return markerView;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,16 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.View;
|
||||
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
import com.mapbox.mapboxsdk.R;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.mapbox.mapboxsdk.maps.MapView;
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMap;
|
||||
|
||||
/**
|
||||
* Marker is an annotation that shows an icon image at a geographical location.
|
||||
*
|
||||
* <p>
|
||||
* An {@link InfoWindow} can be shown when a Marker is pressed
|
||||
* </p>
|
||||
*/
|
||||
public class Marker extends Annotation {
|
||||
|
||||
@@ -20,9 +21,14 @@ public class Marker extends Annotation {
|
||||
private String snippet;
|
||||
private Icon icon;
|
||||
private String title;
|
||||
private InfoWindow infoWindow = null;
|
||||
private boolean infoWindowShown = false;
|
||||
|
||||
private InfoWindow infoWindow;
|
||||
private boolean infoWindowShown;
|
||||
|
||||
private int topOffsetPixels;
|
||||
private int rightOffsetPixels;
|
||||
|
||||
private boolean markerView;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -36,6 +42,7 @@ public class Marker extends Annotation {
|
||||
snippet = baseMarkerOptions.snippet;
|
||||
icon = baseMarkerOptions.icon;
|
||||
title = baseMarkerOptions.title;
|
||||
markerView = baseMarkerOptions.markerView;
|
||||
}
|
||||
|
||||
public LatLng getPosition() {
|
||||
@@ -50,6 +57,10 @@ public class Marker extends Annotation {
|
||||
return title;
|
||||
}
|
||||
|
||||
public boolean isViewMarker() {
|
||||
return markerView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not use this method. Used internally by the SDK.
|
||||
*/
|
||||
@@ -105,6 +116,10 @@ public class Marker extends Annotation {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
void setMarkerView(boolean isMarkerView){
|
||||
markerView = isMarkerView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not use this method. Used internally by the SDK.
|
||||
*/
|
||||
@@ -129,7 +144,7 @@ public class Marker extends Annotation {
|
||||
}
|
||||
|
||||
private InfoWindow showInfoWindow(InfoWindow iw, MapView mapView) {
|
||||
iw.open(mapView, this, getPosition(), 0, topOffsetPixels);
|
||||
iw.open(mapView, this, getPosition(), rightOffsetPixels, topOffsetPixels);
|
||||
infoWindowShown = true;
|
||||
return iw;
|
||||
}
|
||||
@@ -148,6 +163,13 @@ public class Marker extends Annotation {
|
||||
this.topOffsetPixels = topOffsetPixels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not use this method. Used internally by the SDK.
|
||||
*/
|
||||
public void setRightOffsetPixels(int rightOffsetPixels) {
|
||||
this.rightOffsetPixels = rightOffsetPixels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.mapbox.mapboxsdk.annotations;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
|
||||
@@ -38,7 +37,8 @@ public final class MarkerOptions extends BaseMarkerOptions<Marker, MarkerOptions
|
||||
position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
|
||||
snippet(in.readString());
|
||||
title(in.readString());
|
||||
if(in.readByte()!=0){
|
||||
markerView(in.readByte() != 0);
|
||||
if (in.readByte() != 0) {
|
||||
// this means we have an icon
|
||||
String iconId = in.readString();
|
||||
Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
|
||||
@@ -63,6 +63,7 @@ public final class MarkerOptions extends BaseMarkerOptions<Marker, MarkerOptions
|
||||
out.writeString(getSnippet());
|
||||
out.writeString(getTitle());
|
||||
Icon icon = getIcon();
|
||||
out.writeByte((byte) (markerView ? 1 : 0));
|
||||
out.writeByte((byte) (icon != null ? 1 : 0));
|
||||
if (icon != null) {
|
||||
out.writeString(getIcon().getId());
|
||||
@@ -86,6 +87,7 @@ public final class MarkerOptions extends BaseMarkerOptions<Marker, MarkerOptions
|
||||
marker.setSnippet(snippet);
|
||||
marker.setTitle(title);
|
||||
marker.setIcon(icon);
|
||||
marker.setMarkerView(markerView);
|
||||
return marker;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.mapbox.mapboxsdk.annotations;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.AnimatorRes;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public class MarkerViewSettings implements Parcelable {
|
||||
|
||||
private PointF centerOffset;
|
||||
private Point infoWindowOffset;
|
||||
private boolean flat;
|
||||
|
||||
private int animEnterRes;
|
||||
private int animSelectRes;
|
||||
private int animDeselectRes;
|
||||
private int animExitRes;
|
||||
|
||||
MarkerViewSettings(PointF centerOffset, Point infoWindowOffset, boolean flat, int animEnterRes, int animSelectRes, int animDeselectRes, int animExitRes) {
|
||||
this.centerOffset = centerOffset;
|
||||
this.infoWindowOffset = infoWindowOffset;
|
||||
this.flat = flat;
|
||||
this.animEnterRes = animEnterRes;
|
||||
this.animSelectRes = animSelectRes;
|
||||
this.animDeselectRes = animDeselectRes;
|
||||
this.animExitRes = animExitRes;
|
||||
}
|
||||
|
||||
MarkerViewSettings(Parcel parcel) {
|
||||
this.centerOffset = parcel.readParcelable(PointF.class.getClassLoader());
|
||||
this.infoWindowOffset = parcel.readParcelable(Point.class.getClassLoader());
|
||||
this.flat = parcel.readByte() != 0;
|
||||
this.animEnterRes = parcel.readInt();
|
||||
this.animSelectRes = parcel.readInt();
|
||||
this.animDeselectRes = parcel.readInt();
|
||||
this.animExitRes = parcel.readInt();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public PointF getCenterOffset() {
|
||||
return centerOffset;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Point getInfoWindowOffset() {
|
||||
return infoWindowOffset;
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
return flat;
|
||||
}
|
||||
|
||||
@AnimatorRes
|
||||
public int getAnimEnterRes() {
|
||||
return animEnterRes;
|
||||
}
|
||||
|
||||
@AnimatorRes
|
||||
public int getAnimSelectRes() {
|
||||
return animSelectRes;
|
||||
}
|
||||
|
||||
@AnimatorRes
|
||||
public int getAnimDeselectRes() {
|
||||
return animDeselectRes;
|
||||
}
|
||||
|
||||
@AnimatorRes
|
||||
public int getAnimExitRes() {
|
||||
return animExitRes;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<MarkerViewSettings> CREATOR
|
||||
= new Parcelable.Creator<MarkerViewSettings>() {
|
||||
public MarkerViewSettings createFromParcel(Parcel in) {
|
||||
return new MarkerViewSettings(in);
|
||||
}
|
||||
|
||||
public MarkerViewSettings[] newArray(int size) {
|
||||
return new MarkerViewSettings[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(centerOffset, flags);
|
||||
dest.writeParcelable(infoWindowOffset, flags);
|
||||
dest.writeByte((byte) (flat ? 1 : 0));
|
||||
dest.writeInt(animEnterRes);
|
||||
dest.writeInt(animSelectRes);
|
||||
dest.writeInt(animDeselectRes);
|
||||
dest.writeInt(animExitRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for composing LatLngBounds objects.
|
||||
*/
|
||||
public static final class Builder {
|
||||
|
||||
private PointF centerOffset;
|
||||
private Point infoWindowOffset;
|
||||
private boolean flat;
|
||||
|
||||
private int animEnterRes;
|
||||
private int animSelectRes;
|
||||
private int animDeselectRes;
|
||||
private int animExitRes;
|
||||
|
||||
public Builder() {
|
||||
centerOffset = new PointF();
|
||||
infoWindowOffset = new Point();
|
||||
}
|
||||
|
||||
public Builder centerOffset(float dx, float dy) {
|
||||
centerOffset.offset(dx, dy);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder infoWindowOffset(int dx, int dy) {
|
||||
infoWindowOffset.offset(dx, -dy);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder flat(boolean isFlat) {
|
||||
flat = isFlat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder animEnterRes(@AnimatorRes int animatorRes) {
|
||||
animEnterRes = animatorRes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder animSelectRes(@AnimatorRes int animatorRes) {
|
||||
animSelectRes = animatorRes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder animDeselectRes(@AnimatorRes int animatorRes) {
|
||||
animDeselectRes = animatorRes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder animExitRes(@AnimatorRes int animatorRes) {
|
||||
animExitRes = animatorRes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MarkerViewSettings build() {
|
||||
return new MarkerViewSettings(centerOffset, infoWindowOffset, flat, animEnterRes, animSelectRes, animDeselectRes, animExitRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import android.location.Location;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.CallSuper;
|
||||
@@ -35,7 +34,6 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
import android.support.v4.view.GestureDetectorCompat;
|
||||
import android.support.v4.view.ScaleGestureDetectorCompat;
|
||||
import android.support.v4.view.animation.FastOutSlowInInterpolator;
|
||||
@@ -59,7 +57,6 @@ import android.widget.ArrayAdapter;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ZoomButtonsController;
|
||||
|
||||
import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
|
||||
@@ -98,7 +95,6 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -479,88 +475,15 @@ public class MapView extends FrameLayout {
|
||||
if (mViewMarkersUpdateRunning || currentTime < mViewMarkerBoundsUpdateTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
mViewMarkerBoundsUpdateTime = currentTime + 300;
|
||||
|
||||
mViewMarkersUpdateRunning = true;
|
||||
|
||||
List<Marker> inBounds = new ArrayList<>();
|
||||
Map<Marker, View> outBounds = new HashMap<>();
|
||||
mMapboxMap.invalidateViewMarkersInBounds();
|
||||
|
||||
LatLngBounds bounds = mMapboxMap.getProjection().getVisibleRegion().latLngBounds;
|
||||
long[] ids = mNativeMapView.getAnnotationsInBounds(bounds);
|
||||
LongSparseArray<View> markerViews = mMapboxMap.getMarkerViews();
|
||||
Log.v(MapboxConstants.TAG, "Annotations in bounds: " + ids.length);
|
||||
|
||||
boolean found;
|
||||
long key;
|
||||
|
||||
// introduce new markers
|
||||
for (long id : ids) {
|
||||
found = false;
|
||||
for (int i = 0; i < markerViews.size(); i++) {
|
||||
key = markerViews.keyAt(i);
|
||||
|
||||
if (id == key) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
Annotation annotation = mMapboxMap.getAnnotation(id);
|
||||
if (annotation instanceof Marker) {
|
||||
inBounds.add((Marker) annotation);
|
||||
} else {
|
||||
Log.v(MapboxConstants.TAG, "Not instance of Marker" + id);
|
||||
}
|
||||
} else {
|
||||
Log.v(MapboxConstants.TAG, "Already added " + id);
|
||||
}
|
||||
}
|
||||
|
||||
// clean up out of bound markers
|
||||
for (int i = 0; i < markerViews.size(); i++) {
|
||||
found = false;
|
||||
key = markerViews.keyAt(i);
|
||||
for (long id : ids) {
|
||||
if (id == key) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
Annotation annotation = mMapboxMap.getAnnotation(key);
|
||||
if (annotation instanceof Marker) {
|
||||
outBounds.put((Marker) annotation, markerViews.get(key));
|
||||
} else {
|
||||
Log.v(MapboxConstants.TAG, "Not instance of Marker" + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
Result result = new Result(inBounds, outBounds);
|
||||
mMapboxMap.setViewMarkersBoundsTaskResult(result);
|
||||
mViewMarkersUpdateRunning = false;
|
||||
Log.v(MapboxConstants.TAG, "Amount of child views " + getChildCount());
|
||||
}
|
||||
|
||||
public class Result {
|
||||
private List<Marker> inBounds;
|
||||
private Map<Marker, View> outBounds;
|
||||
|
||||
public Result(List<Marker> inBounds, Map<Marker, View> outBounds) {
|
||||
this.inBounds = inBounds;
|
||||
this.outBounds = outBounds;
|
||||
}
|
||||
|
||||
public List<Marker> getInBounds() {
|
||||
return inBounds;
|
||||
}
|
||||
|
||||
public Map<Marker, View> getOutBounds() {
|
||||
return outBounds;
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
/**
|
||||
* You must call this method from the parent's {@link android.app.Activity#onSaveInstanceState(Bundle)}
|
||||
* or {@link android.app.Fragment#onSaveInstanceState(Bundle)}.
|
||||
@@ -970,7 +893,7 @@ public class MapView extends FrameLayout {
|
||||
* <p>
|
||||
* DEPRECATED @see MapboxAccountManager#getAccessToken()
|
||||
* </p>
|
||||
* <p>
|
||||
* <p/>
|
||||
* Returns the current Mapbox access token used to load map styles and tiles.
|
||||
* </p>
|
||||
*
|
||||
@@ -1169,7 +1092,7 @@ public class MapView extends FrameLayout {
|
||||
mNativeMapView.removeAnnotations(ids);
|
||||
}
|
||||
|
||||
private List<Marker> getMarkersInBounds(@NonNull LatLngBounds bbox) {
|
||||
List<Marker> getMarkersInBounds(@NonNull LatLngBounds bbox) {
|
||||
if (mDestroyed || bbox == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
@@ -1438,27 +1361,29 @@ public class MapView extends FrameLayout {
|
||||
mCompassView.update(getDirection());
|
||||
mMyLocationView.update();
|
||||
|
||||
LongSparseArray<View> viewMarkers = mMapboxMap.getMarkerViews();
|
||||
for (int i = 0; i < viewMarkers.size(); i++) {
|
||||
mViewHolder = viewMarkers.valueAt(i);
|
||||
Map<Marker, View> viewMarkers = mMapboxMap.getMarkerViewMap();
|
||||
for (Marker marker : viewMarkers.keySet()) {
|
||||
mViewHolder = viewMarkers.get(marker);
|
||||
if (mViewHolder != null) {
|
||||
Marker marker = (Marker) mMapboxMap.getAnnotation(viewMarkers.keyAt(i));
|
||||
if (marker != null) {
|
||||
PointF point = mMapboxMap.getProjection().toScreenLocation(marker.getPosition());
|
||||
mViewHolder.setX(point.x - (mViewHolder.getMeasuredWidth() / 2));
|
||||
mViewHolder.setY(point.y - (mViewHolder.getMeasuredHeight() / 2));
|
||||
PointF point = mMapboxMap.getProjection().toScreenLocation(marker.getPosition());
|
||||
mViewHolder.setX(point.x - (mViewHolder.getMeasuredWidth() / 2));
|
||||
mViewHolder.setY(point.y - (mViewHolder.getMeasuredHeight() / 2));
|
||||
|
||||
if (mViewHolder.getVisibility() == GONE) {
|
||||
mViewHolder.animate().cancel();
|
||||
mViewHolder.setAlpha(0);
|
||||
mViewHolder.animate().alpha(1).setDuration(MapboxConstants.ANIMATION_DURATION_SHORT).setInterpolator(new FastOutSlowInInterpolator()).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
super.onAnimationStart(animation);
|
||||
mViewHolder.setVisibility(VISIBLE);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
if (mViewHolder.getVisibility() == GONE) {
|
||||
mViewHolder.animate().cancel();
|
||||
mViewHolder.setAlpha(0);
|
||||
mViewHolder.animate()
|
||||
.alpha(1)
|
||||
.setDuration(MapboxConstants.ANIMATION_DURATION_SHORT)
|
||||
.setInterpolator(new FastOutSlowInInterpolator())
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
super.onAnimationStart(animation);
|
||||
mViewHolder.setVisibility(VISIBLE);
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1756,7 +1681,7 @@ public class MapView extends FrameLayout {
|
||||
if (annotation.getId() == newSelectedMarkerId) {
|
||||
if (selectedMarkers.isEmpty() || !selectedMarkers.contains(annotation)) {
|
||||
// only handle click if no marker view is available
|
||||
if(mMapboxMap.getMarkerViews().get(annotation.getId())==null) {
|
||||
if (mMapboxMap.getMarkerViewMap().get(annotation) == null) {
|
||||
mMapboxMap.selectMarker((Marker) annotation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import android.animation.AnimatorInflater;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.location.Location;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.AnimatorRes;
|
||||
@@ -31,6 +33,7 @@ import com.mapbox.mapboxsdk.annotations.IconFactory;
|
||||
import com.mapbox.mapboxsdk.annotations.InfoWindow;
|
||||
import com.mapbox.mapboxsdk.annotations.Marker;
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
|
||||
import com.mapbox.mapboxsdk.annotations.MarkerViewSettings;
|
||||
import com.mapbox.mapboxsdk.annotations.Polygon;
|
||||
import com.mapbox.mapboxsdk.annotations.PolygonOptions;
|
||||
import com.mapbox.mapboxsdk.annotations.Polyline;
|
||||
@@ -49,6 +52,8 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -74,15 +79,14 @@ public class MapboxMap {
|
||||
private LongSparseArray<Annotation> mAnnotations;
|
||||
|
||||
private List<Marker> mSelectedMarkers;
|
||||
private LongSparseArray<View> mMarkerViews;
|
||||
private Map<Marker, View> mMarkerViewMap;
|
||||
private LongSparseArray<MarkerViewSettings> mMarkerViewSettingsMap;
|
||||
|
||||
private List<InfoWindow> mInfoWindows;
|
||||
private MapboxMap.InfoWindowAdapter mInfoWindowAdapter;
|
||||
|
||||
private OnMarkerViewClickListener mOnMarkerViewClickListener;
|
||||
private int mMarkerViewItemAnimatorInRes;
|
||||
private int mMarkerViewItemAnimatorOutRes;
|
||||
private Bitmap mViewMarkerBitmap;
|
||||
private Bitmap mViewMarkerBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
|
||||
|
||||
private boolean mMyLocationEnabled;
|
||||
private boolean mAllowConcurrentMultipleInfoWindows;
|
||||
@@ -112,10 +116,11 @@ public class MapboxMap {
|
||||
mTrackingSettings = new TrackingSettings(mMapView, mUiSettings);
|
||||
mProjection = new Projection(mapView);
|
||||
mAnnotations = new LongSparseArray<>();
|
||||
mMarkerViews = new LongSparseArray<>();
|
||||
mMarkerViewAdapters = new ArrayList<>();
|
||||
mSelectedMarkers = new ArrayList<>();
|
||||
mInfoWindows = new ArrayList<>();
|
||||
mMarkerViewMap = new HashMap<>();
|
||||
mMarkerViewSettingsMap = new LongSparseArray<>();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -648,86 +653,107 @@ public class MapboxMap {
|
||||
// Annotations
|
||||
//
|
||||
|
||||
void setViewMarkersBoundsTaskResult(MapView.Result result) {
|
||||
Map<Marker, View> outBoundsMarker = result.getOutBounds();
|
||||
void invalidateViewMarkersInBounds() {
|
||||
List<Marker> markers = mMapView.getMarkersInBounds(mProjection.getVisibleRegion().latLngBounds);
|
||||
Log.v(MapboxConstants.TAG, "Annotations in bounds: " + markers.size());
|
||||
|
||||
View convertView;
|
||||
|
||||
// out of bounds markers
|
||||
for (Map.Entry<Marker, View> outBoundsEntry : outBoundsMarker.entrySet()) {
|
||||
convertView = outBoundsEntry.getValue();
|
||||
if (convertView != null) {
|
||||
if (mMarkerViewItemAnimatorOutRes != 0) {
|
||||
Animator animator = AnimatorInflater.loadAnimator(mMapView.getContext(), mMarkerViewItemAnimatorOutRes);
|
||||
// remove old markers
|
||||
Iterator<Marker> iterator = mMarkerViewMap.keySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Marker m = iterator.next();
|
||||
if (!markers.contains(m)) {
|
||||
// remove marker
|
||||
convertView = mMarkerViewMap.get(m);
|
||||
MarkerViewSettings settings = mMarkerViewSettingsMap.get(m.getId());
|
||||
int deselectAnimRes = settings.getAnimDeselectRes();
|
||||
if (deselectAnimRes != 0) {
|
||||
Animator animator = AnimatorInflater.loadAnimator(mMapView.getContext(), deselectAnimRes);
|
||||
animator.setDuration(0);
|
||||
animator.setTarget(convertView);
|
||||
animator.start();
|
||||
}
|
||||
removeMarkerView(outBoundsEntry.getKey().getId());
|
||||
removeMarkerView(m);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// in bounds markers
|
||||
List<Marker> inBoundsMarkers = result.getInBounds();
|
||||
for (final Marker marker : inBoundsMarkers) {
|
||||
Log.v("TAG", "Calling get view for " + marker.getId());
|
||||
for (final MarkerViewAdapter adapter : mMarkerViewAdapters) {
|
||||
if (adapter.getMarkerClass() == marker.getClass()) {
|
||||
convertView = (View) adapter.getViewReusePool().acquire();
|
||||
View adaptedView = adapter.getView(marker, convertView, mMapView);
|
||||
if (adaptedView != null) {
|
||||
// hack to hide old marker, todo replace with visibility
|
||||
Icon icon = marker.getIcon();
|
||||
if (!icon.getBitmap().equals(mViewMarkerBitmap)) {
|
||||
if (mViewMarkerBitmap == null) {
|
||||
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
|
||||
mViewMarkerBitmap = Bitmap.createBitmap(icon.getBitmap().getWidth(), icon.getBitmap().getHeight(), conf);
|
||||
// introduce new markers
|
||||
for (final Marker marker : markers) {
|
||||
if (marker.isViewMarker()) {
|
||||
if (!mMarkerViewMap.containsKey(marker)) {
|
||||
Log.v("TAG", "Calling get view for " + marker.getId());
|
||||
for (final MarkerViewAdapter adapter : mMarkerViewAdapters) {
|
||||
if (adapter.getMarkerClass() == marker.getClass()) {
|
||||
|
||||
if (mMarkerViewSettingsMap.get(marker.getId()) == null) {
|
||||
mMarkerViewSettingsMap.put(marker.getId(), adapter.getMarkerViewSettings(marker));
|
||||
}
|
||||
marker.setIcon(IconFactory.recreate(icon.getId(), mViewMarkerBitmap));
|
||||
}
|
||||
|
||||
if (mSelectedMarkers.contains(marker)) {
|
||||
if (mMarkerViewItemAnimatorInRes != 0) {
|
||||
Animator animator = AnimatorInflater.loadAnimator(mMapView.getContext(), mMarkerViewItemAnimatorInRes);
|
||||
animator.setDuration(0);
|
||||
animator.setTarget(convertView);
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
convertView = (View) adapter.getViewReusePool().acquire();
|
||||
View adaptedView = adapter.getView(marker, convertView, mMapView);
|
||||
|
||||
adaptedView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// set user provided offset to view marker
|
||||
final MarkerViewSettings markerViewSettings = mMarkerViewSettingsMap.get(marker.getId());
|
||||
Point infoWindowOffset = markerViewSettings.getInfoWindowOffset();
|
||||
marker.setTopOffsetPixels(infoWindowOffset.y);
|
||||
marker.setRightOffsetPixels(infoWindowOffset.x);
|
||||
|
||||
boolean clickHandled = false;
|
||||
if (mOnMarkerViewClickListener != null) {
|
||||
clickHandled = mOnMarkerViewClickListener.onMarkerClick(marker, v, adapter);
|
||||
}
|
||||
|
||||
if (!clickHandled) {
|
||||
if (mMarkerViewItemAnimatorInRes != 0) {
|
||||
Animator animator = AnimatorInflater.loadAnimator(mMapView.getContext(), mMarkerViewItemAnimatorInRes);
|
||||
animator.setTarget(v);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
selectMarker(marker);
|
||||
}
|
||||
});
|
||||
if (adaptedView != null) {
|
||||
if (mSelectedMarkers.contains(marker)) {
|
||||
// if a marker to be shown was selected
|
||||
// replay that animation with duration 0
|
||||
int selectAnimRes = markerViewSettings.getAnimSelectRes();
|
||||
if (selectAnimRes != 0) {
|
||||
Animator animator = AnimatorInflater.loadAnimator(mMapView.getContext(), selectAnimRes);
|
||||
animator.setDuration(0);
|
||||
animator.setTarget(convertView);
|
||||
animator.start();
|
||||
} else {
|
||||
selectMarker(marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mMarkerViews.append(marker.getId(), adaptedView);
|
||||
if (convertView == null) {
|
||||
mMapView.addView(adaptedView);
|
||||
adaptedView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
boolean clickHandled = false;
|
||||
if (mOnMarkerViewClickListener != null) {
|
||||
clickHandled = mOnMarkerViewClickListener.onMarkerClick(marker, v, adapter);
|
||||
}
|
||||
|
||||
if (!clickHandled) {
|
||||
int enterAnimatorRes = markerViewSettings.getAnimSelectRes();
|
||||
if (enterAnimatorRes != 0) {
|
||||
Animator animator = AnimatorInflater.loadAnimator(mMapView.getContext(), enterAnimatorRes);
|
||||
animator.setTarget(v);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
selectMarker(marker);
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
} else {
|
||||
selectMarker(marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mMarkerViewMap.put(marker, adaptedView);
|
||||
if (convertView == null) {
|
||||
mMapView.addView(adaptedView);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//already added
|
||||
Log.v(MapboxConstants.TAG, "Marker already added");
|
||||
}
|
||||
} else {
|
||||
Log.v(MapboxConstants.TAG, "Marker is not a view marker");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1010,16 +1036,16 @@ public class MapboxMap {
|
||||
if (annotation instanceof Marker) {
|
||||
Marker marker = (Marker) annotation;
|
||||
marker.hideInfoWindow();
|
||||
removeMarkerView(annotation.getId());
|
||||
removeMarkerView(marker);
|
||||
mMarkerViewMap.remove(marker);
|
||||
}
|
||||
long id = annotation.getId();
|
||||
mMapView.removeAnnotation(id);
|
||||
mAnnotations.remove(id);
|
||||
}
|
||||
|
||||
private void removeMarkerView(long id) {
|
||||
final View viewHolder = mMarkerViews.get(id);
|
||||
final Marker marker = (Marker) getAnnotation(id);
|
||||
private void removeMarkerView(Marker marker) {
|
||||
final View viewHolder = mMarkerViewMap.get(marker);
|
||||
if (viewHolder != null && marker != null) {
|
||||
for (final MarkerViewAdapter<?> adapter : mMarkerViewAdapters) {
|
||||
if (adapter.getMarkerClass() == marker.getClass()) {
|
||||
@@ -1047,9 +1073,7 @@ public class MapboxMap {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
mMarkerViews.remove(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1075,8 +1099,10 @@ public class MapboxMap {
|
||||
for (int i = 0; i < count; i++) {
|
||||
Annotation annotation = annotationList.get(i);
|
||||
if (annotation instanceof Marker) {
|
||||
((Marker) annotation).hideInfoWindow();
|
||||
removeMarkerView(annotation.getId());
|
||||
Marker marker = (Marker) annotation;
|
||||
marker.hideInfoWindow();
|
||||
removeMarkerView(marker);
|
||||
mMarkerViewMap.remove(marker);
|
||||
}
|
||||
ids[i] = annotationList.get(i).getId();
|
||||
}
|
||||
@@ -1098,8 +1124,10 @@ public class MapboxMap {
|
||||
ids[i] = mAnnotations.keyAt(i);
|
||||
annotation = mAnnotations.get(ids[i]);
|
||||
if (annotation instanceof Marker) {
|
||||
((Marker) annotation).hideInfoWindow();
|
||||
removeMarkerView(annotation.getId());
|
||||
Marker marker = (Marker) annotation;
|
||||
marker.hideInfoWindow();
|
||||
removeMarkerView(marker);
|
||||
mMarkerViewMap.remove(marker);
|
||||
}
|
||||
}
|
||||
mMapView.removeAnnotations(ids);
|
||||
@@ -1251,11 +1279,14 @@ public class MapboxMap {
|
||||
marker.hideInfoWindow();
|
||||
}
|
||||
|
||||
View viewMarker = mMarkerViews.get(marker.getId());
|
||||
View viewMarker = mMarkerViewMap.get(marker);
|
||||
if (viewMarker != null) {
|
||||
Animator animator = AnimatorInflater.loadAnimator(mMapView.getContext(), mMarkerViewItemAnimatorOutRes);
|
||||
animator.setTarget(viewMarker);
|
||||
animator.start();
|
||||
int deselectAnimatorRes = mMarkerViewSettingsMap.get(marker.getId()).getAnimDeselectRes();
|
||||
if (deselectAnimatorRes != 0) {
|
||||
Animator animator = AnimatorInflater.loadAnimator(mMapView.getContext(), deselectAnimatorRes);
|
||||
animator.setTarget(viewMarker);
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1291,8 +1322,13 @@ public class MapboxMap {
|
||||
|
||||
private Marker prepareMarker(BaseMarkerOptions markerOptions) {
|
||||
Marker marker = markerOptions.getMarker();
|
||||
Icon icon = mMapView.loadIconForMarker(marker);
|
||||
marker.setTopOffsetPixels(mMapView.getTopOffsetPixelsForIcon(icon));
|
||||
if (markerOptions.isViewMarker()) {
|
||||
Icon icon = IconFactory.recreate("markerViewSettings", mViewMarkerBitmap);
|
||||
marker.setIcon(icon);
|
||||
} else {
|
||||
Icon icon = mMapView.loadIconForMarker(marker);
|
||||
marker.setTopOffsetPixels(mMapView.getTopOffsetPixelsForIcon(icon));
|
||||
}
|
||||
return marker;
|
||||
}
|
||||
|
||||
@@ -1311,25 +1347,6 @@ public class MapboxMap {
|
||||
mOnMarkerViewClickListener = listener;
|
||||
}
|
||||
|
||||
public OnMarkerViewClickListener getOnMarkerViewClickListener() {
|
||||
return mOnMarkerViewClickListener;
|
||||
}
|
||||
|
||||
public void setMarkerViewItemAnimation(@AnimatorRes int animationInRes, @AnimatorRes int animationOutRes) {
|
||||
mMarkerViewItemAnimatorInRes = animationInRes;
|
||||
mMarkerViewItemAnimatorOutRes = animationOutRes;
|
||||
}
|
||||
|
||||
@AnimatorRes
|
||||
public int getMarkerViewItemAnimatorInRes() {
|
||||
return mMarkerViewItemAnimatorInRes;
|
||||
}
|
||||
|
||||
@AnimatorRes
|
||||
public int getMarkerViewItemAnimatorOutRes() {
|
||||
return mMarkerViewItemAnimatorOutRes;
|
||||
}
|
||||
|
||||
//
|
||||
// InfoWindow
|
||||
//
|
||||
@@ -1385,9 +1402,8 @@ public class MapboxMap {
|
||||
return mInfoWindows;
|
||||
}
|
||||
|
||||
// used by MapView
|
||||
LongSparseArray<View> getMarkerViews() {
|
||||
return mMarkerViews;
|
||||
Map<Marker, View> getMarkerViewMap() {
|
||||
return mMarkerViewMap;
|
||||
}
|
||||
|
||||
private boolean isInfoWindowValidForMarker(@NonNull Marker marker) {
|
||||
@@ -1920,17 +1936,19 @@ public class MapboxMap {
|
||||
|
||||
public static abstract class MarkerViewAdapter<U extends Marker> {
|
||||
|
||||
private Context context;
|
||||
private final Class<U> persistentClass;
|
||||
private final Pools.SimplePool<View> mViewReusePool;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public MarkerViewAdapter(Context context) {
|
||||
this.context = context;
|
||||
persistentClass = (Class<U>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
|
||||
mViewReusePool = new Pools.SimplePool<>(20);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract View getView(@NonNull U marker, @Nullable View convertView, @NonNull ViewGroup parent);
|
||||
public abstract View getView(@NonNull U marker, @NonNull View convertView, @NonNull ViewGroup parent);
|
||||
|
||||
public Class<U> getMarkerClass() {
|
||||
return persistentClass;
|
||||
@@ -1939,6 +1957,15 @@ public class MapboxMap {
|
||||
public Pools.SimplePool<View> getViewReusePool() {
|
||||
return mViewReusePool;
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public MarkerViewSettings getMarkerViewSettings(Marker marker) {
|
||||
return new MarkerViewSettings.Builder().build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface OnMarkerViewClickListener {
|
||||
|
||||
Reference in New Issue
Block a user