Merge branch 'release-android-v4.1.0'

# Conflicts:
#	platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java
#	platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
#	platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
#	platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
#	platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
#	platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
#	platform/android/src/jni.cpp
#	src/mbgl/geometry/buffer.hpp
#	src/mbgl/geometry/glyph_atlas.cpp
#	src/mbgl/geometry/glyph_atlas.hpp
#	src/mbgl/geometry/line_atlas.cpp
#	src/mbgl/geometry/vao.cpp
#	src/mbgl/gl/gl_object_store.cpp
#	src/mbgl/gl/gl_object_store.hpp
#	src/mbgl/renderer/frame_history.cpp
#	src/mbgl/shader/shader.cpp
#	src/mbgl/sprite/sprite_atlas.cpp
#	src/mbgl/sprite/sprite_atlas.hpp
#	src/mbgl/text/glyph_pbf.hpp
This commit is contained in:
Brad Leege
2016-06-09 14:00:49 -05:00
66 changed files with 1177 additions and 646 deletions

View File

@@ -23,6 +23,7 @@ public abstract class Annotation implements Comparable<Annotation> {
*/
private long id = -1; // -1 unless added to a MapView
protected MapboxMap mapboxMap;
protected MapView mapView;
protected Annotation() {
}
@@ -68,6 +69,22 @@ public abstract class Annotation implements Comparable<Annotation> {
return mapboxMap;
}
/**
* Don not use this method. Used internally by the SDK.
*/
public void setMapView(MapView mapView) {
this.mapView = mapView;
}
/**
* Gets the associated MapView
*
* @return The MapView
*/
protected MapView getMapView() {
return mapView;
}
@Override
public int compareTo(@NonNull Annotation annotation) {
if (id < annotation.getId()) {

View File

@@ -1,7 +1,7 @@
package com.mapbox.mapboxsdk.annotations;
import android.os.Parcelable;
import android.support.annotation.AnimatorRes;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
import com.mapbox.mapboxsdk.geometry.LatLng;
@@ -26,10 +26,9 @@ public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends Base
protected float anchorV = 1f;
protected float infoWindowAnchorU = 0.5f;
protected float infoWindowAnchorV = 0.0f;
protected int selectAnimRes;
protected int deselectAnimRes;
protected int rotation;
protected float rotation;
protected boolean visible = true;
protected boolean selected;
/**
* Default constructor
@@ -99,7 +98,7 @@ public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends Base
* @param v the v-value
* @return the object for which the method was called
*/
public T anchor(float u, float v) {
public T anchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
this.anchorU = u;
this.anchorV = v;
return getThis();
@@ -112,41 +111,19 @@ public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends Base
* @param v the v-values
* @return the object for which the method was called
*/
public T infoWindowAnchor(float u, float v) {
public T infoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
this.infoWindowAnchorU = u;
this.infoWindowAnchorV = v;
return getThis();
}
/**
* Set the animator resource to be used when an MarkerView is selected.
*
* @param selectAnimRes the used animator resource
* @return the object for which the method was called
*/
public T selectAnimatorResource(@AnimatorRes int selectAnimRes) {
this.selectAnimRes = selectAnimRes;
return getThis();
}
/**
* Set the animator resource to be used when an MarkerView is deselected.
*
* @param deselectAnimRes the used animator resource
* @return the object for which the method was called
*/
public T deselectAnimatorResource(@AnimatorRes int deselectAnimRes) {
this.deselectAnimRes = deselectAnimRes;
return getThis();
}
/**
* Set the rotation of the MarkerView.
*
* @param rotation the rotation value
* @return the object for which the method was called
*/
public T rotation(int rotation) {
public T rotation(float rotation) {
this.rotation = rotation;
return getThis();
}
@@ -243,30 +220,12 @@ public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends Base
return infoWindowAnchorV;
}
/**
* Get the animator resource used for selecting the MarkerView.
*
* @return the animator resource
*/
public int getSelectAnimRes() {
return selectAnimRes;
}
/**
* Get the animator resource used for deselecting the MarkerView.
*
* @return the animator resource
*/
public int getDeselectAnimRes() {
return deselectAnimRes;
}
/**
* Get the rotation of the MarkerView.
*
* @return the rotation value
*/
public int getRotation() {
public float getRotation() {
return rotation;
}

View File

@@ -3,7 +3,6 @@ package com.mapbox.mapboxsdk.annotations;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
@@ -91,8 +90,9 @@ public class Marker extends Annotation {
}
}
void setSnippet(String snippet) {
public void setSnippet(String snippet) {
this.snippet = snippet;
refreshInfoWindowContent();
}
/**
@@ -112,8 +112,25 @@ public class Marker extends Annotation {
return icon;
}
void setTitle(String title) {
public void setTitle(String title) {
this.title = title;
refreshInfoWindowContent();
}
/**
* Update only for default Marker's InfoWindow content for Title and Snippet
*/
private void refreshInfoWindowContent() {
if (isInfoWindowShown() && mapView != null && mapboxMap != null && mapboxMap.getInfoWindowAdapter() == null) {
InfoWindow infoWindow = getInfoWindow(mapView);
if (mapView.getContext() != null) {
infoWindow.adaptDefaultMarker(this, mapboxMap, mapView);
}
MapboxMap map = getMapboxMap();
if (map != null) {
map.updateMarker(this);
}
}
}
/**
@@ -121,6 +138,7 @@ public class Marker extends Annotation {
*/
public InfoWindow showInfoWindow(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) {
setMapboxMap(mapboxMap);
setMapView(mapView);
MapboxMap.InfoWindowAdapter infoWindowAdapter = getMapboxMap().getInfoWindowAdapter();
if (infoWindowAdapter != null) {
// end developer is using a custom InfoWindowAdapter

View File

@@ -1,5 +1,12 @@
package com.mapbox.mapboxsdk.annotations;
import android.graphics.Bitmap;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.maps.MapboxMap;
/**
@@ -28,13 +35,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
*/
@@ -53,12 +61,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;
}
/**
@@ -71,7 +78,7 @@ public class MarkerView extends Marker {
* @param u u-coordinate of the anchor, as a ratio of the image width (in the range [0, 1])
* @param v v-coordinate of the anchor, as a ratio of the image height (in the range [0, 1])
*/
public void setAnchor(float u, float v) {
public void setAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
this.anchorU = u;
this.anchorV = v;
}
@@ -149,7 +156,7 @@ public class MarkerView extends Marker {
* @param v v-coordinate of the info window anchor, as a ratio of the image height (in the range [0, 1])
* @see #setAnchor(float, float) for more details.
*/
public void setInfoWindowAnchor(float u, float v) {
public void setInfoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) {
this.infoWindowAnchorU = u;
this.infoWindowAnchorV = v;
}
@@ -190,42 +197,6 @@ public class MarkerView extends Marker {
this.flat = flat;
}
/**
* 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.
*
@@ -240,7 +211,7 @@ public class MarkerView extends Marker {
*
* @param tiltValue the tilted value to set
*/
void setTilt(float tiltValue) {
void setTilt(@FloatRange(from = 0.0, to = MapboxConstants.MAXIMUM_TILT) float tiltValue) {
this.tiltValue = tiltValue;
}
@@ -308,13 +279,52 @@ public class MarkerView extends Marker {
*
* @param alpha the alpha value to animate to
*/
public void setAlpha(float alpha) {
public void setAlpha(@FloatRange(from=0.0, to=255.0)float alpha) {
this.alpha = alpha;
if (markerViewManager != null) {
markerViewManager.animateAlpha(this, alpha);
}
}
/**
* Set the icon of the MarkerView.
*
* @param icon the icon to be used as Marker image
*/
@Override
public void setIcon(@Nullable Icon icon) {
if (icon != null) {
markerViewIcon = IconFactory.recreate("icon", icon.getBitmap());
}
Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Icon transparentIcon = IconFactory.recreate("markerViewSettings", bitmap);
if (markerViewManager != null) {
markerViewManager.updateIcon(this);
}
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.
*
* @return the icon use as Marker image
*/
@Override
public Icon getIcon() {
return markerViewIcon;
}
/**
* Set the MapboxMap associated tot the MapView containing the MarkerView.
* <p>

View File

@@ -1,12 +1,17 @@
package com.mapbox.mapboxsdk.annotations;
import android.content.Context;
import android.graphics.PointF;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pools;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Projection;
@@ -26,12 +31,13 @@ import java.util.Map;
*/
public class MarkerViewManager {
private Map<MarkerView, View> mMarkerViewMap;
private Map<MarkerView, View> markerViewMap;
private MapboxMap mapboxMap;
private MapView mapView;
private List<MapboxMap.MarkerViewAdapter> markerViewAdapters;
private long mViewMarkerBoundsUpdateTime;
private long viewMarkerBoundsUpdateTime;
private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener;
private ImageMarkerViewAdapter defaultMarkerViewAdapter;
/**
* Creates an instance of MarkerViewManager.
@@ -43,7 +49,9 @@ public class MarkerViewManager {
this.mapboxMap = mapboxMap;
this.markerViewAdapters = new ArrayList<>();
this.mapView = mapView;
mMarkerViewMap = new HashMap<>();
this.markerViewMap = new HashMap<>();
this.defaultMarkerViewAdapter = new ImageMarkerViewAdapter(mapView.getContext());
this.markerViewAdapters.add(defaultMarkerViewAdapter);
}
/**
@@ -56,7 +64,7 @@ public class MarkerViewManager {
* @param rotation the rotation value
*/
public void animateRotation(@NonNull MarkerView marker, float rotation) {
View convertView = mMarkerViewMap.get(marker);
View convertView = markerViewMap.get(marker);
if (convertView != null) {
AnimatorUtils.rotate(convertView, rotation);
}
@@ -72,7 +80,7 @@ public class MarkerViewManager {
* @param alpha the alpha value
*/
public void animateAlpha(@NonNull MarkerView marker, float alpha) {
View convertView = mMarkerViewMap.get(marker);
View convertView = markerViewMap.get(marker);
if (convertView != null) {
AnimatorUtils.alpha(convertView, alpha);
}
@@ -88,7 +96,7 @@ public class MarkerViewManager {
* @param visible the flag indicating if MarkerView is visible
*/
public void animateVisible(@NonNull MarkerView marker, boolean visible) {
View convertView = mMarkerViewMap.get(marker);
View convertView = markerViewMap.get(marker);
if (convertView != null) {
convertView.setVisibility(visible ? View.VISIBLE : View.GONE);
}
@@ -104,8 +112,8 @@ public class MarkerViewManager {
*/
public void update() {
View convertView;
for (MarkerView marker : mMarkerViewMap.keySet()) {
convertView = mMarkerViewMap.get(marker);
for (MarkerView marker : markerViewMap.keySet()) {
convertView = markerViewMap.get(marker);
if (convertView != null) {
PointF point = mapboxMap.getProjection().toScreenLocation(marker.getPosition());
int x = (int) (marker.getAnchorU() * convertView.getMeasuredWidth());
@@ -133,9 +141,9 @@ public class MarkerViewManager {
*/
public void setTilt(float tilt) {
View convertView;
for (MarkerView markerView : mMarkerViewMap.keySet()) {
for (MarkerView markerView : markerViewMap.keySet()) {
if (markerView.isFlat()) {
convertView = mMarkerViewMap.get(markerView);
convertView = markerViewMap.get(markerView);
if (convertView != null) {
markerView.setTilt(tilt);
convertView.setRotationX(tilt);
@@ -144,70 +152,119 @@ public class MarkerViewManager {
}
}
/**
*
*/
public void updateIcon(@NonNull MarkerView markerView) {
View convertView = markerViewMap.get(markerView);
if (convertView != null && convertView instanceof ImageView) {
((ImageView) convertView).setImageBitmap(markerView.getIcon().getBitmap());
}
}
/**
* 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 com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)} will be called to execute an animation.
* </p>
*
* @param marker the MarkerView to deselect
*/
public void deselect(@NonNull MarkerView marker) {
final View convertView = mMarkerViewMap.get(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);
}
}
}
}
/**
* Animate a MarkerView to a selected state.
*
* @param marker the MarkerView object to select
*/
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);
}
}
}
/**
* Animate a MarkerView to a selected state.
* <p>
* The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)} will be called to execute an animation.
* </p>
* @param marker the MarkerView object to select
* @param convertView the View presentation of the MarkerView
* @param adapter the adapter used to adapt the marker to the convertView
*/
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);
}
}
/**
* Get view representation from a MarkerView.
* <p>
* If marker is not found in current viewport, null is returned.
* </p>
*
* @param marker the marker to get the view for
* @return the android SDK View object
*/
@Nullable
public View getView(MarkerView marker) {
return markerViewMap.get(marker);
}
/**
* Remove a MarkerView from a map.
* <p>
* The {@link MarkerView} will be removed using an alpha animation and related {@link View}
* will be released to the {@link android.support.v4.util.Pools.SimplePool} from the related
* will be released to the android.support.v4.util.Pools.SimplePool from the related
* {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}. It's possible to remove
* 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) {
final View viewHolder = mMarkerViewMap.get(marker);
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) {
mMarkerViewMap.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();
@@ -223,7 +280,6 @@ public class MarkerViewManager {
return markerViewAdapters;
}
/**
* Register a callback to be invoked when this view is clicked.
*
@@ -243,11 +299,11 @@ public class MarkerViewManager {
public void scheduleViewMarkerInvalidation() {
if (!markerViewAdapters.isEmpty()) {
long currentTime = SystemClock.elapsedRealtime();
if (currentTime < mViewMarkerBoundsUpdateTime) {
if (currentTime < viewMarkerBoundsUpdateTime) {
return;
}
invalidateViewMarkersInBounds();
mViewMarkerBoundsUpdateTime = currentTime + 250;
viewMarkerBoundsUpdateTime = currentTime + 250;
}
}
@@ -264,26 +320,27 @@ public class MarkerViewManager {
View convertView;
// remove old markers
Iterator<MarkerView> iterator = mMarkerViewMap.keySet().iterator();
Iterator<MarkerView> iterator = markerViewMap.keySet().iterator();
while (iterator.hasNext()) {
MarkerView m = iterator.next();
if (!markers.contains(m)) {
// remove marker
convertView = mMarkerViewMap.get(m);
int deselectAnimRes = m.getDeselectAnimRes();
if (deselectAnimRes != 0) {
AnimatorUtils.animate(convertView, deselectAnimRes, 0);
convertView = markerViewMap.get(m);
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();
}
}
// introduce new markers
for (final MarkerView marker : markers) {
if (!mMarkerViewMap.containsKey(marker)) {
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) {
@@ -303,13 +360,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) {
@@ -324,22 +379,12 @@ 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);
}
}
});
mMarkerViewMap.put(marker, adaptedView);
markerViewMap.put(marker, adaptedView);
if (convertView == null) {
mapView.addView(adaptedView);
}
@@ -349,4 +394,37 @@ public class MarkerViewManager {
}
}
}
/**
* Default MarkerViewAdapter used for base class of MarkerView to adapt a MarkerView to an ImageView
*/
public static class ImageMarkerViewAdapter extends MapboxMap.MarkerViewAdapter<MarkerView> {
private LayoutInflater inflater;
public ImageMarkerViewAdapter(Context context) {
super(context);
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_image_marker, parent, false);
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.image);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.imageView.setImageBitmap(marker.getIcon().getBitmap());
return convertView;
}
private static class ViewHolder {
ImageView imageView;
}
}
}

View File

@@ -28,9 +28,7 @@ public class MarkerViewOptions extends BaseMarkerViewOptions<MarkerView, MarkerV
flat(in.readByte() != 0);
anchor(in.readFloat(), in.readFloat());
infoWindowAnchor(in.readFloat(), in.readFloat());
selectAnimatorResource(in.readInt());
deselectAnimatorResource(in.readInt());
rotation(in.readInt());
rotation(in.readFloat());
visible(in.readByte() != 0);
if (in.readByte() != 0) {
// this means we have an icon
@@ -61,9 +59,7 @@ public class MarkerViewOptions extends BaseMarkerViewOptions<MarkerView, MarkerV
out.writeFloat(getAnchorV());
out.writeFloat(getInfoWindowAnchorU());
out.writeFloat(getInfoWindowAnchorV());
out.writeInt(getSelectAnimRes());
out.writeInt(getDeselectAnimRes());
out.writeInt(getRotation());
out.writeFloat(getRotation());
out.writeByte((byte) (isVisible() ? 1 : 0));
Icon icon = getIcon();
out.writeByte((byte) (icon != null ? 1 : 0));
@@ -82,8 +78,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;

View File

@@ -1,7 +1,9 @@
package com.mapbox.mapboxsdk.constants;
import android.support.annotation.StringDef;
import com.mapbox.mapboxsdk.maps.MapView;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -15,168 +17,32 @@ import java.lang.annotation.RetentionPolicy;
*/
public class Style {
/**
* Mapbox Streets: A complete basemap, perfect for incorporating your own data.
*/
private static final String MAPBOX_STREETS_BASE = "mapbox://styles/mapbox/streets-v%d";
/**
* Outdoors: A general-purpose style tailored to outdoor activities.
*/
private static final String OUTDOORS_BASE = "mapbox://styles/mapbox/outdoors-v%d";
/**
* Light: Subtle light backdrop for data visualizations.
*/
private static final String LIGHT_BASE = "mapbox://styles/mapbox/light-v%d";
/**
* Dark: Subtle dark backdrop for data visualizations.
*/
private static final String DARK_BASE = "mapbox://styles/mapbox/dark-v%d";
/**
* Satellite: A beautiful global satellite and aerial imagery layer.
*/
private static final String SATELLITE_BASE = "mapbox://styles/mapbox/satellite-v%d";
/**
* Satellite Streets: Global satellite and aerial imagery with unobtrusive labels.
*/
private static final String SATELLITE_STREETS_BASE = "mapbox://styles/mapbox/satellite-streets-v%d";
/**
* Satellite Streets: Global satellite and aerial imagery with unobtrusive labels (Version 8).
* Indicates the parameter accepts one of the values from {@link Style}. Using one of these
* constants means your map style will always use the latest version and may change as we
* improve the style
*/
private static final String SATELLITE_STREETS_V8 = "mapbox://styles/mapbox/satellite-hybrid-v8";
/**
* Get versioned url of Mapbox streets style.
* <p>
* <ul>
* <li>Current default version is 9.</li>
* </ul
* </p>
* <p>
* More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
* </p>
*
* @param version the version of the style.
* @return uri to load style from
*/
public static String getMapboxStreetsUrl(int version) {
return String.format(MapboxConstants.MAPBOX_LOCALE, MAPBOX_STREETS_BASE, version);
}
/**
* Get versioned url of Outdoors streets style.
* <p>
* <ul>
* <li>Current version is 9.</li>
* </ul>
* </p>
* <p>
* More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
* </p>
*
* @param version the version of the style.
* @return uri to load style from
*/
public static String getOutdoorsStyleUrl(int version) {
return String.format(MapboxConstants.MAPBOX_LOCALE, OUTDOORS_BASE, version);
}
/**
* Get versioned url of Light style.
* <p>
* <ul>
* <li>Current default version is 9.</li>
* </ul>
* </p>
* <p>
* More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
* </p>
*
* @param version the version of the style.
* @return uri to load style from
*/
public static String getLightStyleUrl(int version) {
return String.format(MapboxConstants.MAPBOX_LOCALE, LIGHT_BASE, version);
}
/**
* Get versioned url of Dark style.
* <p>
* <ul>
* <li>Current default version is 9.</li>
* </ul>
* </p>
* <p>
* More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
* </p>
*
* @param version the version of the style.
* @return uri to load style from
*/
public static String getDarkStyleUrl(int version) {
return String.format(MapboxConstants.MAPBOX_LOCALE, DARK_BASE, version);
}
/**
* Get versioned url of Satellite style.
* <p>
* <ul>
* <li>Current version is 9.</li>
* </ul>
* </p>
* <p>
* More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
* </p>
*
* @param version the version of the style.
* @return uri to load style from
*/
public static String getSatelliteStyleUrl(int version) {
return String.format(MapboxConstants.MAPBOX_LOCALE, SATELLITE_BASE, version);
}
/**
* Get versioned url of Satellite streets style.
* <p>
* <ul>
* <li>Current version is 9.</li>
* </ul>
* </p>
* <p>
* More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
* </p>
*
* @param version the version of the style.
* @return uri to load style from
*/
public static String getSatelliteStreetsStyleUrl(int version) {
if (version == 8) {
return SATELLITE_STREETS_V8;
}
return String.format(MapboxConstants.MAPBOX_LOCALE, SATELLITE_STREETS_BASE, version);
}
/**
* Indicates the parameter accepts one of the values from {@link Style}.
*
* @deprecated use dedicated versioned methods in {@link Style} instead.
*/
@StringDef({MAPBOX_STREETS, EMERALD, LIGHT, DARK, SATELLITE, SATELLITE_STREETS})
@StringDef({MAPBOX_STREETS, OUTDOORS, EMERALD, LIGHT, DARK, SATELLITE, SATELLITE_STREETS})
@Retention(RetentionPolicy.SOURCE)
@Deprecated
public @interface StyleUrl {
}
// IMPORTANT: If you change any of these you also need to edit them in strings.xml
/**
* Mapbox Streets: A complete basemap, perfect for incorporating your own data.
*
* @deprecated use {@link #getMapboxStreetsUrl(int)} instead.
* Mapbox Streets: A complete basemap, perfect for incorporating your own data. Using this
* constant means your map style will always use the latest version and may change as we
* improve the style.
*/
@Deprecated
public static final String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v9";
/**
* Outdoors: A general-purpose style tailored to outdoor activities. Using this constant means
* your map style will always use the latest version and may change as we improve the style.
*/
public static final String OUTDOORS = "mapbox://styles/mapbox/outdoors-v9";
/**
* Emerald: A versatile style, with emphasis on road networks and public transit.
*
@@ -186,34 +52,27 @@ public class Style {
public static final String EMERALD = "mapbox://styles/mapbox/emerald-v8";
/**
* Light: Subtle light backdrop for data visualizations.
*
* @deprecated use {@link #getLightStyleUrl(int)} instead.
* Light: Subtle light backdrop for data visualizations. Using this constant means your map
* style will always use the latest version and may change as we improve the style.
*/
@Deprecated
public static final String LIGHT = "mapbox://styles/mapbox/light-v9";
/**
* Dark: Subtle dark backdrop for data visualizations.
*
* @deprecated use {@link #getDarkStyleUrl(int)} (int)} instead.
* Dark: Subtle dark backdrop for data visualizations. Using this constant means your map style
* will always use the latest version and may change as we improve the style.
*/
@Deprecated
public static final String DARK = "mapbox://styles/mapbox/dark-v9";
/**
* Satellite: A beautiful global satellite and aerial imagery layer.
*
* @deprecated use {@link #getSatelliteStyleUrl(int)} instead.
* Satellite: A beautiful global satellite and aerial imagery layer. Using this constant means
* your map style will always use the latest version and may change as we improve the style.
*/
@Deprecated
public static final String SATELLITE = "mapbox://styles/mapbox/satellite-v9";
/**
* Satellite Streets: Global satellite and aerial imagery with unobtrusive labels.
*
* @deprecated use {@link #getSatelliteStreetsStyleUrl(int)} (int)} instead.
* Satellite Streets: Global satellite and aerial imagery with unobtrusive labels. Using this
* constant means your map style will always use the latest version and may change as we
* improve the style.
*/
@Deprecated
public static final String SATELLITE_STREETS = "mapbox://styles/mapbox/satellite-streets-v9";
}

View File

@@ -18,12 +18,10 @@ import java.util.concurrent.CopyOnWriteArrayList;
/**
* Manages locational updates. Contains methods to register and unregister location listeners.
* <p>
* <ul>
* <li>You can register a {@link LocationListener} with {@link #addLocationListener(LocationListener)} to receive location updates.</li>
* <li> You can unregister a {@link LocationListener} with {@link #removeLocationListener(LocationListener)}.</li>
* </ul>
* <p/>
* <p>
* Note: If registering a listener in your Activity.onResume() implementation, you should unregister it in Activity.onPause().
* (You won't receive location updates when paused, and this will cut down on unnecessary system overhead).

View File

@@ -252,6 +252,7 @@ public class MapView extends FrameLayout {
CameraPosition position = options.getCamera();
if (position != null) {
mMapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(position));
mMyLocationView.setTilt(position.tilt);
}
String accessToken = null;
@@ -407,7 +408,6 @@ public class MapView extends FrameLayout {
// User location
try {
//noinspection ResourceType
mMapboxMap.setMyLocationEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED));
} catch (SecurityException ignore) {
// User did not accept location permissions
@@ -445,6 +445,7 @@ public class MapView extends FrameLayout {
callback.onMapReady(mMapboxMap);
iterator.remove();
}
mMapboxMap.getMarkerViewManager().scheduleViewMarkerInvalidation();
}
} else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) {
mMapboxMap.getMarkerViewManager().scheduleViewMarkerInvalidation();
@@ -672,11 +673,11 @@ public class MapView extends FrameLayout {
return mContentPaddingBottom;
}
int getContentWidth(){
int getContentWidth() {
return getWidth() - mContentPaddingLeft - mContentPaddingRight;
}
int getContentHeight(){
int getContentHeight() {
return getHeight() - mContentPaddingBottom - mContentPaddingTop;
}
@@ -783,7 +784,7 @@ public class MapView extends FrameLayout {
* <li>{@code asset://...}:
* reads the style from the APK {@code assets/} directory.
* This is used to load a style bundled with your app.</li>
* <li>{@code null}: loads the default {@link Style#getMapboxStreetsUrl(int)} style.</li>
* <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
* </ul>
* <p>
* This method is asynchronous and will return immediately before the style finishes loading.
@@ -874,7 +875,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>
*
@@ -993,7 +994,10 @@ public class MapView extends FrameLayout {
Log.w(MapboxConstants.TAG, "marker has an id of -1, possibly was not added yet, doing nothing");
}
ensureIconLoaded(updatedMarker);
if (!(updatedMarker instanceof MarkerView)) {
ensureIconLoaded(updatedMarker);
}
mNativeMapView.updateMarker(updatedMarker);
}
@@ -1021,7 +1025,7 @@ public class MapView extends FrameLayout {
}
long addMarker(@NonNull Marker marker) {
if(mDestroyed){
if (mDestroyed) {
return 0l;
}
return mNativeMapView.addMarker(marker);
@@ -2708,7 +2712,7 @@ public class MapView extends FrameLayout {
private boolean mDefaultStyle;
StyleInitializer(@NonNull Context context) {
mStyle = Style.getMapboxStreetsUrl(context.getResources().getInteger(R.integer.style_version));
mStyle = Style.MAPBOX_STREETS;
mDefaultStyle = true;
}

View File

@@ -20,7 +20,6 @@ import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
@@ -72,7 +71,6 @@ public class MapboxMap {
private List<InfoWindow> mInfoWindows;
private MapboxMap.InfoWindowAdapter mInfoWindowAdapter;
private Bitmap mViewMarkerBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
private boolean mMyLocationEnabled;
private boolean mAllowConcurrentMultipleInfoWindows;
@@ -291,7 +289,7 @@ public class MapboxMap {
* it will return the current location of the camera in flight.
*
* @param update The change that should be applied to the camera.
* @see {@link CameraUpdateFactory} for a set of updates.
* @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
*/
@UiThread
public final void easeCamera(CameraUpdate update) {
@@ -306,7 +304,7 @@ public class MapboxMap {
* @param update The change that should be applied to the camera.
* @param durationMs The duration of the animation in milliseconds. This must be strictly
* positive, otherwise an IllegalArgumentException will be thrown.
* @see {@link CameraUpdateFactory} for a set of updates.
* @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
*/
@UiThread
public final void easeCamera(CameraUpdate update, int durationMs) {
@@ -327,7 +325,7 @@ public class MapboxMap {
* will be notified with onFinish(). If the animation stops due to interruption
* by a later camera movement or a user gesture, onCancel() will be called.
* Do not update or ease the camera from within onCancel().
* @see {@link CameraUpdateFactory} for a set of camera updates.
* @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
*/
@UiThread
public final void easeCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
@@ -368,7 +366,7 @@ public class MapboxMap {
* of the camera in flight.
*
* @param update The change that should be applied to the camera.
* @see {@link CameraUpdateFactory} for a set of updates.
* @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
*/
@UiThread
public final void animateCamera(CameraUpdate update) {
@@ -385,7 +383,7 @@ public class MapboxMap {
* @param callback The callback to invoke from the main thread when the animation stops. If the
* animation completes normally, onFinish() is called; otherwise, onCancel() is
* called. Do not update or animate the camera from within onCancel().
* @see {@link CameraUpdateFactory} for a set of updates.
* @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
*/
@UiThread
public final void animateCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) {
@@ -401,7 +399,7 @@ public class MapboxMap {
* @param update The change that should be applied to the camera.
* @param durationMs The duration of the animation in milliseconds. This must be strictly
* positive, otherwise an IllegalArgumentException will be thrown.
* @see {@link CameraUpdateFactory} for a set of updates.
* @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
*/
@UiThread
public final void animateCamera(CameraUpdate update, int durationMs) {
@@ -424,7 +422,7 @@ public class MapboxMap {
* by a later camera movement or a user gesture, onCancel() will be called.
* Do not update or animate the camera from within onCancel(). If a callback
* isn't required, leave it as null.
* @see {@link CameraUpdateFactory} for a set of updates.
* @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates.
*/
@UiThread
public final void animateCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
@@ -550,7 +548,7 @@ public class MapboxMap {
* <li>{@code asset://...}:
* reads the style from the APK {@code assets/} directory.
* This is used to load a style bundled with your app.</li>
* <li>{@code null}: loads the default {@link Style#getMapboxStreetsUrl(int)} style.</li>
* <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
* </ul>
* <p>
* This method is asynchronous and will return immediately before the style finishes loading.
@@ -703,10 +701,11 @@ public class MapboxMap {
@NonNull
public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions) {
MarkerView marker = prepareViewMarker(markerOptions);
long id = mMapView.addMarker(marker);
marker.setMapboxMap(this);
long id = mMapView.addMarker(marker);
marker.setId(id);
mAnnotations.put(id, marker);
mMarkerViewManager.invalidateViewMarkersInBounds();
return marker;
}
@@ -952,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();
@@ -986,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();
@@ -1012,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);
}
}
}
@@ -1209,8 +1208,7 @@ public class MapboxMap {
private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) {
MarkerView marker = markerViewOptions.getMarker();
Icon icon = IconFactory.recreate("markerViewSettings", mViewMarkerBitmap);
marker.setIcon(icon);
marker.setIcon(markerViewOptions.getIcon());
return marker;
}
@@ -1287,9 +1285,11 @@ public class MapboxMap {
//
/**
* <p>
* Sets the distance from the edges of the map view’s frame to the edges of the map
* view’s logical viewport.
* <p/>
* </p>
* <p>
* When the value of this property is equal to {0,0,0,0}, viewport
* properties such as `centerCoordinate` assume a viewport that matches the map
* view’s frame. Otherwise, those properties are inset, excluding part of the
@@ -1826,7 +1826,7 @@ public class MapboxMap {
public MarkerViewAdapter(Context context) {
this.context = context;
persistentClass = (Class<U>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
mViewReusePool = new Pools.SimplePool<>(20);
mViewReusePool = new Pools.SimplePool<>(10000);
}
/**
@@ -1840,12 +1840,57 @@ public class MapboxMap {
@Nullable
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);
}
}
/**

View File

@@ -462,6 +462,16 @@ public class MapboxMapOptions implements Parcelable {
return this;
}
/**
*
* @param myLocationForegroundDrawable
* @return This
*/
public MapboxMapOptions myLocationForegroundDrawable(Drawable myLocationForegroundDrawable) {
this.myLocationForegroundDrawable = myLocationForegroundDrawable;
return this;
}
/**
* @param myLocationBackgroundDrawable
* @return This

View File

@@ -7,6 +7,7 @@ import android.graphics.RectF;
import android.os.Build;
import android.view.Surface;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.Polyline;
@@ -370,7 +371,9 @@ final class NativeMapView {
}
public void updateMarker(Marker marker) {
nativeUpdateMarker(mNativeMapViewPtr, marker);
LatLng position = marker.getPosition();
Icon icon = marker.getIcon();
nativeUpdateMarker(mNativeMapViewPtr, marker.getId(), position.getLatitude(), position.getLongitude(), icon.getId());
}
public void removeAnnotation(long id) {
@@ -462,7 +465,7 @@ final class NativeMapView {
nativeRemoveCustomLayer(mNativeMapViewPtr, id);
}
public double[] getCameraValues(){
public double[] getCameraValues() {
return nativeGetCameraValues(mNativeMapViewPtr);
}

View File

@@ -3,8 +3,10 @@ package com.mapbox.mapboxsdk.maps.widgets;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff;
@@ -15,6 +17,8 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.SystemClock;
import android.support.annotation.ColorInt;
import android.support.annotation.FloatRange;
@@ -22,6 +26,7 @@ import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.camera.CameraPosition;
@@ -33,7 +38,6 @@ import com.mapbox.mapboxsdk.location.LocationListener;
import com.mapbox.mapboxsdk.location.LocationServices;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Projection;
import com.mapbox.mapboxsdk.maps.UiSettings;
import java.lang.ref.WeakReference;
@@ -45,7 +49,6 @@ public class MyLocationView extends View {
private MyLocationBehavior myLocationBehavior;
private MapboxMap mapboxMap;
private Projection projection;
private int maxSize;
private int[] contentPadding = new int[4];
private Location location;
@@ -57,12 +60,12 @@ public class MyLocationView extends View {
private float gpsDirection;
private float previousDirection;
private float accuracy = 0;
private Paint accuracyPaint = new Paint();
private float accuracy;
private Paint accuracyPaint;
private ValueAnimator locationChangeAnimator;
private ValueAnimator accuracyAnimator;
private ObjectAnimator directionAnimator;
private ValueAnimator directionAnimator;
private Drawable foregroundDrawable;
private Drawable foregroundBearingDrawable;
@@ -79,6 +82,11 @@ public class MyLocationView extends View {
private int backgroundOffsetRight;
private int backgroundOffsetBottom;
private Matrix matrix;
private Camera camera;
private PointF screenLocation;
private float tilt;
@MyLocationTracking.Mode
private int myLocationTrackingMode;
@@ -105,15 +113,39 @@ public class MyLocationView extends View {
private void init(Context context) {
setEnabled(false);
// setup LayoutParams
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
setLayoutParams(lp);
matrix = new Matrix();
camera = new Camera();
camera.setLocation(0, 0, -1000);
accuracyPaint = new Paint();
myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE);
compassListener = new CompassListener(context);
maxSize = (int) context.getResources().getDimension(R.dimen.my_locationview_size);
}
public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) {
if (defaultDrawable == null || bearingDrawable == null) {
if (defaultDrawable == null) {
return;
}
if (bearingDrawable == null) {
// if user only provided one resource
// use same for bearing mode
bearingDrawable = defaultDrawable.getConstantState().newDrawable();
}
if (backgroundDrawable == null) {
// if the user didn't provide a background resource we will use the foreground resource instead,
// we need to create a new drawable to handle tinting correctly
backgroundDrawable = defaultDrawable.getConstantState().newDrawable();
}
if (defaultDrawable.getIntrinsicWidth() != bearingDrawable.getIntrinsicWidth() || defaultDrawable.getIntrinsicHeight() != bearingDrawable.getIntrinsicHeight()) {
throw new RuntimeException("The dimensions from location and bearing drawables should be match");
}
@@ -151,7 +183,6 @@ public class MyLocationView extends View {
backgroundOffsetTop = top;
backgroundOffsetRight = right;
backgroundOffsetBottom = bottom;
setShadowDrawableTint(backgroundTintColor);
invalidateBounds();
@@ -187,19 +218,18 @@ public class MyLocationView extends View {
int backgroundWidth = backgroundDrawable.getIntrinsicWidth();
int backgroundHeight = backgroundDrawable.getIntrinsicHeight();
int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight;
int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom;
backgroundBounds = new Rect(-backgroundWidth / 2 + horizontalOffset, -backgroundHeight / 2 + verticalOffset, backgroundWidth / 2 + horizontalOffset, backgroundHeight / 2 + verticalOffset);
backgroundDrawable.setBounds(backgroundBounds);
int foregroundWidth = foregroundDrawable.getIntrinsicWidth();
int foregroundHeight = foregroundDrawable.getIntrinsicHeight();
foregroundBounds = new Rect(-foregroundWidth / 2, -foregroundHeight / 2, foregroundWidth / 2, foregroundHeight / 2);
foregroundDrawable.setBounds(foregroundBounds);
foregroundBearingDrawable.setBounds(foregroundBounds);
int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight;
int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom;
int accuracyWidth = 2 * maxSize;
backgroundBounds = new Rect(accuracyWidth - (backgroundWidth / 2) + horizontalOffset, accuracyWidth + verticalOffset - (backgroundWidth / 2), accuracyWidth + (backgroundWidth / 2) + horizontalOffset, accuracyWidth + (backgroundHeight / 2) + verticalOffset);
foregroundBounds = new Rect(accuracyWidth - (foregroundWidth / 2), accuracyWidth - (foregroundHeight / 2), accuracyWidth + (foregroundWidth / 2), accuracyWidth + (foregroundHeight / 2));
// invoke a new measure
// invoke a new draw
invalidate();
}
@@ -207,23 +237,51 @@ public class MyLocationView extends View {
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null) {
if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null || screenLocation == null) {
// Not ready yet
return;
}
// Draw circle
float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude());
float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel;
float maxRadius = getWidth() / 2;
canvas.drawCircle(foregroundBounds.centerX(), foregroundBounds.centerY(), accuracyPixels <= maxRadius ? accuracyPixels : maxRadius, accuracyPaint);
final PointF pointF = screenLocation;
// Draw shadow
float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude());
float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel / 2;
float maxRadius = getWidth() / 2;
accuracyPixels = accuracyPixels <= maxRadius ? accuracyPixels : maxRadius;
// put matrix in origin
matrix.reset();
// apply tilt to camera
camera.save();
camera.rotate(tilt, 0, 0);
// map camera matrix on our matrix
camera.getMatrix(matrix);
//
if (myBearingTrackingMode != MyBearingTracking.NONE) {
matrix.postRotate((Float) directionAnimator.getAnimatedValue());
}
// put matrix at location of MyLocationView
matrix.postTranslate(pointF.x, pointF.y);
// concat our matrix on canvas
canvas.concat(matrix);
// restore orientation from camera
camera.restore();
// draw circle
canvas.drawCircle(0, 0, accuracyPixels, accuracyPaint);
// draw shadow
if (backgroundDrawable != null) {
backgroundDrawable.draw(canvas);
}
// Draw foreground
// draw foreground
if (myBearingTrackingMode == MyBearingTracking.NONE) {
if (foregroundDrawable != null) {
foregroundDrawable.draw(canvas);
@@ -233,27 +291,8 @@ public class MyLocationView extends View {
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (foregroundDrawable != null && foregroundBounds != null) {
foregroundDrawable.setBounds(foregroundBounds);
}
if (foregroundBearingDrawable != null && foregroundBounds != null) {
foregroundBearingDrawable.setBounds(foregroundBounds);
}
if (backgroundDrawable != null && backgroundBounds != null) {
backgroundDrawable.setBounds(backgroundBounds);
}
setMeasuredDimension(4 * maxSize, 4 * maxSize);
}
public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) {
setRotationX((float) tilt);
this.tilt = (float) tilt;
}
void updateOnNextFrame() {
@@ -294,6 +333,24 @@ public class MyLocationView extends View {
toggleGps(enabled);
}
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putParcelable("superState", super.onSaveInstanceState());
bundle.putFloat("tilt", tilt);
return bundle;
}
@Override
public void onRestoreInstanceState(Parcelable state){
if (state instanceof Bundle){
Bundle bundle = (Bundle) state;
tilt = bundle.getFloat("tilt");
state = bundle.getParcelable("superState");
}
super.onRestoreInstanceState(state);
}
/**
* Enabled / Disable GPS location updates along with updating the UI
*
@@ -385,8 +442,8 @@ public class MyLocationView extends View {
}
previousDirection = newDir;
directionAnimator = ObjectAnimator.ofFloat(this, View.ROTATION, oldDir, newDir);
directionAnimator.setDuration(1000);
directionAnimator = ValueAnimator.ofFloat(oldDir, newDir);
directionAnimator.setDuration(375);
directionAnimator.start();
}
@@ -626,9 +683,9 @@ public class MyLocationView extends View {
@Override
void invalidate() {
int[] mapPadding = mapboxMap.getPadding();
UiSettings uiSettings = mapboxMap.getUiSettings();
setX((uiSettings.getWidth() - getWidth() + mapPadding[0] - mapPadding[2]) / 2 + (contentPadding[0] - contentPadding[2]) / 2);
setY((uiSettings.getHeight() - getHeight() - mapPadding[3] + mapPadding[1]) / 2 + (contentPadding[1] - contentPadding[3]) / 2);
float x = (getWidth() + mapPadding[0] - mapPadding[2]) / 2 + (contentPadding[0] - contentPadding[2]) / 2;
float y = (getHeight() - mapPadding[3] + mapPadding[1]) / 2 + (contentPadding[1] - contentPadding[3]) / 2;
screenLocation = new PointF(x, y);
MyLocationView.this.invalidate();
}
}
@@ -659,7 +716,7 @@ public class MyLocationView extends View {
// calculate updateLatLng time + add some extra offset to improve animation
long previousUpdateTimeStamp = locationUpdateTimestamp;
locationUpdateTimestamp = SystemClock.elapsedRealtime();
long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1);
long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.3);
// calculate interpolated entity
interpolatedLocation = new LatLng((latLng.getLatitude() + previousLocation.getLatitude()) / 2, (latLng.getLongitude() + previousLocation.getLongitude()) / 2);
@@ -694,11 +751,7 @@ public class MyLocationView extends View {
@Override
void invalidate() {
PointF screenLocation = projection.toScreenLocation(latLng);
if (screenLocation != null) {
setX((screenLocation.x - getWidth() / 2));
setY((screenLocation.y - getHeight() / 2));
}
screenLocation = projection.toScreenLocation(latLng);
MyLocationView.this.invalidate();
}
}

View File

@@ -6,6 +6,9 @@ import android.support.annotation.IntRange;
import com.mapbox.mapboxsdk.maps.MapView;
/**
* Settings to configure the visual appearance of the MyLocationView.
*/
public class MyLocationViewSettings {
private MapView mapView;
@@ -52,43 +55,101 @@ public class MyLocationViewSettings {
private int[] padding = new int[4];
/**
* Creates an instance of MyLocationViewSettings
*
* @param mapView the MapView that hosts the MyLocationView
* @param myLocationView the MyLocationView to apply the settings to
* @see MyLocationView
*/
public MyLocationViewSettings(MapView mapView, MyLocationView myLocationView) {
this.mapView = mapView;
this.myLocationView = myLocationView;
}
/**
* Returns if the MyLocationView is enabled
*
* @return true if MyLocationView is enabled,
*/
public boolean isEnabled() {
return enabled;
}
/**
* Set the enabled state of MyLocationView
*
* @param enabled true shows the MyLocationView on the map
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
myLocationView.setEnabled(enabled);
}
/**
* Set the foreground drawable of the MyLocationView
* <p>
* The foreground drawable is the image visible on screen
* </p>
*
* @param foregroundDrawable the drawable to show as foreground without bearing
* @param foregroundBearingDrawable the drawable to show as foreground when bearing is enabled
*/
public void setForegroundDrawable(Drawable foregroundDrawable, Drawable foregroundBearingDrawable) {
this.foregroundDrawable = foregroundDrawable;
this.foregroundBearingDrawable = foregroundBearingDrawable;
myLocationView.setForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
}
/**
* Get the foreground drawable when bearing is disabled.
*
* @return the drawable used as foreground
*/
public Drawable getForegroundDrawable() {
return foregroundDrawable;
}
/**
* Get the foreground drawable when bearing is enabled.
*
* @return the bearing drawable used as foreground
*/
public Drawable getForegroundBearingDrawable() {
return foregroundBearingDrawable;
}
/**
* Set the foreground tint color.
* <p>
* The color will tint both the foreground and the bearing foreground drawable.
* </p>
*
* @param foregroundTintColor the color to tint the foreground drawable
*/
public void setForegroundTintColor(@ColorInt int foregroundTintColor) {
this.foregroundTintColor = foregroundTintColor;
myLocationView.setForegroundDrawableTint(foregroundTintColor);
}
/**
* Get the foreground tint color.
*
* @return the foreground tint color
*/
public int getForegroundTintColor() {
return foregroundTintColor;
}
/**
* Set the background drawable of MyLocationView
* <p>
* Padding can be added to provide an offset to the background
* </p>
*
* @param backgroundDrawable the drawable to show as background
* @param padding the padding added to the background
*/
public void setBackgroundDrawable(Drawable backgroundDrawable, int[] padding) {
this.backgroundDrawable = backgroundDrawable;
this.backgroundOffset = padding;
@@ -99,46 +160,99 @@ public class MyLocationViewSettings {
}
}
/**
* Get the background drawable of MyLocationView.
*
* @return the drawable used as background
*/
public Drawable getBackgroundDrawable() {
return backgroundDrawable;
}
/**
* Set the background tint color.
*
* @param backgroundTintColor the color to tint the background
*/
public void setBackgroundTintColor(@ColorInt int backgroundTintColor) {
this.backgroundTintColor = backgroundTintColor;
myLocationView.setShadowDrawableTint(backgroundTintColor);
}
/**
* Get the background tint color.
*
* @return the background tint color
*/
public int getBackgroundTintColor() {
return backgroundTintColor;
}
/**
* Get the background offset.
*
* @return the background offset
*/
public int[] getBackgroundOffset() {
return backgroundOffset;
}
/**
* Set the MyLocationView padding.
*
* @param left the padding left of MyLocationView
* @param top the padding top of MyLocationView
* @param right the padding right of MyLocationView
* @param bottom the padding bottom of MyLocaionView
*/
public void setPadding(int left, int top, int right, int bottom) {
padding = new int[]{left, top, right, bottom};
myLocationView.setContentPadding(padding);
mapView.invalidateContentPadding();
}
/**
* Get the MyLocationView padding.
*
* @return an array describing the padding in a LTRB manner
*/
public int[] getPadding() {
return padding;
}
/**
* Get the alpha value of the accuracy circle of MyLocationView
*
* @return the alpha value
*/
public int getAccuracyAlpha() {
return accuracyAlpha;
}
public void setAccuracyAlpha(@IntRange(from = 0, to = 255) int arruracyAlpha) {
this.accuracyAlpha = arruracyAlpha;
myLocationView.setAccuracyAlpha(arruracyAlpha);
/**
* Set the alpha value of the accuracy circle of MyLocationView
*
* @param accuracyAlpha the alpha value to set
*/
public void setAccuracyAlpha(@IntRange(from = 0, to = 255) int accuracyAlpha) {
this.accuracyAlpha = accuracyAlpha;
myLocationView.setAccuracyAlpha(accuracyAlpha);
}
/**
* Get the accuracy tint color of MyLocationView.
*
* @return the tint color used for accuracy
*/
public int getAccuracyTintColor() {
return accuracyTintColor;
}
/**
* Set the accuracy tint color of MyLocationView.
*
* @param accuracyTintColor the accuracy tint color
*/
public void setAccuracyTintColor(@ColorInt int accuracyTintColor) {
this.accuracyTintColor = accuracyTintColor;
myLocationView.setAccuracyTint(accuracyTintColor);

View File

@@ -7,7 +7,7 @@ import java.io.Serializable;
*/
public class MapboxEvent implements Serializable {
public static final int VERSION_NUMBER = 2;
public static final String MAPBOX_EVENTS_BASE_URL = "https://api.mapbox.com";
public static final String MAPBOX_EVENTS_BASE_URL = "https://events.mapbox.com";
public static final String SOURCE_MAPBOX = "mapbox";
// Event Types

View File

@@ -686,19 +686,20 @@ public class MapboxEventManager {
.add("cloudfront-staging.tilestream.net", "sha256/sPbNCVpVasMJxps3IqFfLTRKkVnRCLrTlZVc5kspqlkw=")
.add("cloudfront-staging.tilestream.net", "sha256/h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=")
// Prod - Geotrust
.add("api.mapbox.com", "sha256/svaiYM/ZVIfxC+CMDe4kj1KsviQmzyZ9To8nQqUJwFI=")
.add("api.mapbox.com", "sha256/owrR9U9FWDWtrFF+myoRIu75JwU4sJwzvhCNLZoY37g=")
.add("api.mapbox.com", "sha256/SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=")
.add("events.mapbox.com", "sha256/BhynraKizavqoC5U26qgYuxLZst6pCu9J5stfL6RSYY=")
.add("events.mapbox.com", "sha256/owrR9U9FWDWtrFF+myoRIu75JwU4sJwzvhCNLZoY37g=")
.add("events.mapbox.com", "sha256/SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=")
// Prod - DigiCert
.add("api.mapbox.com", "sha256/JL+uwAwpA2U1UVl/AFdZy1ZnvkZJ1P1hRfmfPaPVSLU=")
.add("api.mapbox.com", "sha256/RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=")
.add("api.mapbox.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=")
.add("events.mapbox.com", "sha256/Tb0uHZ/KQjWh8N9+CZFLc4zx36LONQ55l6laDi1qtT4=")
.add("events.mapbox.com", "sha256/RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=")
.add("events.mapbox.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=")
.build();
OkHttpClient client = new OkHttpClient.Builder().certificatePinner(certificatePinner).build();
RequestBody body = RequestBody.create(JSON, jsonArray.toString());
String url = eventsURL + "/events/v2?access_token=" + accessToken;
// Log.d(TAG, "Events URL = " + url);
Request request = new Request.Builder()
.url(url)