summaryrefslogtreecommitdiff
path: root/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk
diff options
context:
space:
mode:
authorTobrun <tobrun.van.nuland@gmail.com>2016-12-06 13:46:49 +0100
committerGitHub <noreply@github.com>2016-12-06 13:46:49 +0100
commit9a9e7978db67276cfaab97e00f2b56eeb0222b12 (patch)
tree0da54e64117a64195ee46060e01d270a86c1e45d /platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk
parent890b681b182f7d538237604307da487f3619d1b1 (diff)
downloadqtlocation-mapboxgl-9a9e7978db67276cfaab97e00f2b56eeb0222b12.tar.gz
[android] - Refactor dependencies, introduce focused components (#7189)
* [android] - refactor dependencies * ignore tests
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk')
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java43
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java107
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java21
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java8
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java601
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java264
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java1806
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java383
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java54
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java66
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java99
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java157
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java161
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java48
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java20
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java79
19 files changed, 1899 insertions, 2036 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
index 1073818ca4..ce2d3d1577 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
@@ -9,6 +9,7 @@ import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import com.mapbox.mapboxsdk.R;
@@ -31,27 +32,31 @@ import java.util.Map;
*/
public class MarkerViewManager {
- private Map<MarkerView, View> markerViewMap;
+ private final ViewGroup markerViewContainer;
+ private final Map<MarkerView, View> markerViewMap = new HashMap<>();
+ private final List<MapboxMap.MarkerViewAdapter> markerViewAdapters = new ArrayList<>();
+
+ // TODO refactor MapboxMap out for Projection and Transform
+ // Requires removing MapboxMap from Annotations by using Peer model from #6912
private MapboxMap mapboxMap;
- private MapView mapView;
- private List<MapboxMap.MarkerViewAdapter> markerViewAdapters;
+
private long viewMarkerBoundsUpdateTime;
private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener;
- private ImageMarkerViewAdapter defaultMarkerViewAdapter;
/**
* Creates an instance of MarkerViewManager.
*
- * @param mapboxMap the MapboxMap associated with the MarkerViewManager
- * @param mapView the MapView associated with the MarkerViewManager
+ * @param container the ViewGroup associated with the MarkerViewManager
*/
- public MarkerViewManager(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) {
+ public MarkerViewManager(@NonNull ViewGroup container) {
+ this.markerViewContainer = container;
+ this.markerViewAdapters.add(new ImageMarkerViewAdapter(container.getContext()));
+ }
+
+ // TODO refactor MapboxMap out for Projection and Transform
+ // Requires removing MapboxMap from Annotations by using Peer model from #6912
+ public void bind(MapboxMap mapboxMap){
this.mapboxMap = mapboxMap;
- this.markerViewAdapters = new ArrayList<>();
- this.mapView = mapView;
- this.markerViewMap = new HashMap<>();
- this.defaultMarkerViewAdapter = new ImageMarkerViewAdapter(mapView.getContext());
- this.markerViewAdapters.add(defaultMarkerViewAdapter);
}
/**
@@ -415,7 +420,7 @@ public class MarkerViewManager {
* </p>
*/
public void invalidateViewMarkersInVisibleRegion() {
- RectF mapViewRect = new RectF(0, 0, mapView.getWidth(), mapView.getHeight());
+ RectF mapViewRect = new RectF(0, 0, markerViewContainer.getWidth(), markerViewContainer.getHeight());
List<MarkerView> markers = mapboxMap.getMarkerViewsInRect(mapViewRect);
View convertView;
@@ -445,7 +450,7 @@ public class MarkerViewManager {
// Inflate View
convertView = (View) adapter.getViewReusePool().acquire();
- final View adaptedView = adapter.getView(marker, convertView, mapView);
+ final View adaptedView = adapter.getView(marker, convertView, markerViewContainer);
if (adaptedView != null) {
adaptedView.setRotationX(marker.getTilt());
adaptedView.setRotation(marker.getRotation());
@@ -464,7 +469,7 @@ public class MarkerViewManager {
markerViewMap.put(marker, adaptedView);
if (convertView == null) {
adaptedView.setVisibility(View.GONE);
- mapView.getMarkerViewContainer().addView(adaptedView);
+ markerViewContainer.addView(adaptedView);
}
}
}
@@ -515,7 +520,7 @@ public class MarkerViewManager {
for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
if (adapter.getMarkerClass().equals(marker.getClass())) {
View convertView = (View) adapter.getViewReusePool().acquire();
- view = adapter.getView(marker, convertView, mapView);
+ view = adapter.getView(marker, convertView, markerViewContainer);
break;
}
}
@@ -523,7 +528,7 @@ public class MarkerViewManager {
if (view != null) {
if (marker.getWidth() == 0) {
- if(view.getMeasuredWidth()==0) {
+ if (view.getMeasuredWidth() == 0) {
//Ensure the marker's view is measured first
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
}
@@ -546,6 +551,10 @@ public class MarkerViewManager {
}
}
+ public ViewGroup getMarkerViewContainer() {
+ return markerViewContainer;
+ }
+
/**
* Default MarkerViewAdapter used for base class of {@link MarkerView} to adapt a MarkerView to
* an ImageView.
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
index 9c96450a4c..04105ebc59 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
@@ -257,7 +257,7 @@ public final class CameraUpdateFactory {
float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width;
float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height;
minScale = scaleX < scaleY ? scaleX : scaleY;
- zoom = projection.calculateZoom(minScale);
+ zoom = calculateZoom(mapboxMap, minScale);
zoom = MathUtils.clamp(zoom, mapboxMap.getMinZoom(), mapboxMap.getMaxZoom());
}
@@ -275,6 +275,16 @@ public final class CameraUpdateFactory {
.bearing(0)
.build();
}
+
+ /**
+ * Calculates a zoom level based on minimum scale and current scale from MapView
+ *
+ * @param minScale The minimum scale to calculate the zoom level.
+ * @return zoom level that fits the MapView.
+ */
+ public double calculateZoom(MapboxMap mapboxMap, float minScale) {
+ return Math.log(mapboxMap.getCameraPosition().zoom * minScale) / Math.log(2);
+ }
}
static final class CameraMoveUpdate implements CameraUpdate {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
index 9e08d93bfc..c1cf966eed 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
@@ -1,9 +1,11 @@
package com.mapbox.mapboxsdk.maps;
+import android.graphics.PointF;
import android.graphics.RectF;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.LongSparseArray;
+import android.view.ViewGroup;
import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
@@ -18,6 +20,7 @@ import com.mapbox.mapboxsdk.annotations.Polyline;
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -32,30 +35,38 @@ import java.util.List;
*/
class AnnotationManager implements MapView.OnMapChangedListener {
- private NativeMapView nativeMapView;
- private IconManager iconManager;
- private InfoWindowManager infoWindowManager;
- private MarkerViewManager markerViewManager;
+ private final NativeMapView nativeMapView;
+ private final MapView mapView;
+ private final IconManager iconManager;
+ private final InfoWindowManager infoWindowManager = new InfoWindowManager();
+ private final MarkerViewManager markerViewManager;
+ private final LongSparseArray<Annotation> annotations = new LongSparseArray<>();
+ private final List<Marker> selectedMarkers = new ArrayList<>();
- private LongSparseArray<Annotation> annotations;
- private List<Marker> selectedMarkers;
+ private MapboxMap mapboxMap;
private MapboxMap.OnMarkerClickListener onMarkerClickListener;
private boolean isWaitingForRenderInvoke;
- AnnotationManager(NativeMapView view, IconManager iconManager, InfoWindowManager manager) {
+ AnnotationManager(NativeMapView view, MapView mapView, MarkerViewManager markerViewManager) {
this.nativeMapView = view;
- this.iconManager = iconManager;
- this.infoWindowManager = manager;
- this.selectedMarkers = new ArrayList<>();
- this.annotations = new LongSparseArray<>();
-
+ this.mapView = mapView;
+ this.iconManager = new IconManager(nativeMapView);
+ this.markerViewManager = markerViewManager;
if (view != null) {
// null checking needed for unit tests
view.addOnMapChangedListener(this);
}
}
+ // TODO refactor MapboxMap out for Projection and Transform
+ // Requires removing MapboxMap from Annotations by using Peer model from #6912
+ AnnotationManager bind(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ this.markerViewManager.bind(mapboxMap);
+ return this;
+ }
+
@Override
public void onMapChanged(@MapView.MapChange int change) {
if (isWaitingForRenderInvoke && change == MapView.DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) {
@@ -280,7 +291,7 @@ class AnnotationManager implements MapView.OnMapChangedListener {
onMarkerClickListener = listener;
}
- void selectMarker(@NonNull Marker marker, @NonNull MapboxMap mapboxMap) {
+ void selectMarker(@NonNull Marker marker) {
if (selectedMarkers.contains(marker)) {
return;
}
@@ -303,7 +314,7 @@ class AnnotationManager implements MapView.OnMapChangedListener {
}
if (infoWindowManager.isInfoWindowValidForMarker(marker) || infoWindowManager.getInfoWindowAdapter() != null) {
- infoWindowManager.add(marker.showInfoWindow(mapboxMap, mapboxMap.getMapView()));
+ infoWindowManager.add(marker.showInfoWindow(mapboxMap, mapView));
}
}
@@ -564,14 +575,11 @@ class AnnotationManager implements MapView.OnMapChangedListener {
return polylines;
}
- //
- // MarkerViewManager
- //
+ InfoWindowManager getInfoWindowManager() {
+ return infoWindowManager;
+ }
- MarkerViewManager getMarkerViewManager(MapboxMap mapboxMap) {
- if (markerViewManager == null) {
- this.markerViewManager = new MarkerViewManager(mapboxMap, mapboxMap.getMapView());
- }
+ MarkerViewManager getMarkerViewManager() {
return markerViewManager;
}
@@ -589,12 +597,13 @@ class AnnotationManager implements MapView.OnMapChangedListener {
for (Marker marker : selectedMarkers) {
if (marker.isInfoWindowShown()) {
marker.hideInfoWindow();
- marker.showInfoWindow(mapboxMap, mapboxMap.getMapView());
+ marker.showInfoWindow(mapboxMap, mapView);
}
}
}
void reloadMarkers() {
+ iconManager.reloadIcons();
int count = annotations.size();
for (int i = 0; i < count; i++) {
Annotation annotation = annotations.get(i);
@@ -606,4 +615,58 @@ class AnnotationManager implements MapView.OnMapChangedListener {
}
}
}
+
+ //
+ // Click event
+ //
+
+ boolean onTap(PointF tapPoint, float screenDensity) {
+ float toleranceSides = 4 * screenDensity;
+ float toleranceTopBottom = 10 * screenDensity;
+
+ RectF tapRect = new RectF(tapPoint.x - iconManager.getAverageIconWidth() / 2 - toleranceSides,
+ tapPoint.y - iconManager.getAverageIconHeight() / 2 - toleranceTopBottom,
+ tapPoint.x + iconManager.getAverageIconWidth() / 2 + toleranceSides,
+ tapPoint.y + iconManager.getAverageIconHeight() / 2 + toleranceTopBottom);
+
+ List<Marker> nearbyMarkers = getMarkersInRect(tapRect);
+ long newSelectedMarkerId = -1;
+
+ if (nearbyMarkers != null && nearbyMarkers.size() > 0) {
+ Collections.sort(nearbyMarkers);
+ for (Marker nearbyMarker : nearbyMarkers) {
+ boolean found = false;
+ for (Marker selectedMarker : selectedMarkers) {
+ if (selectedMarker.equals(nearbyMarker)) {
+ found = true;
+ }
+ }
+ if (!found) {
+ newSelectedMarkerId = nearbyMarker.getId();
+ break;
+ }
+ }
+ }
+
+ if (newSelectedMarkerId >= 0) {
+ List<Annotation> annotations = getAnnotations();
+ int count = annotations.size();
+ for (int i = 0; i < count; i++) {
+ Annotation annotation = annotations.get(i);
+ if (annotation instanceof Marker) {
+ if (annotation.getId() == newSelectedMarkerId) {
+ if (selectedMarkers.isEmpty() || !selectedMarkers.contains(annotation)) {
+ if (!(annotation instanceof MarkerView)) {
+ selectMarker((Marker) annotation);
+ } else {
+ markerViewManager.onClickMarkerView((MarkerView) annotation);
+ }
+ }
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java
deleted file mode 100644
index 3e1b14d641..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CompassViewSettings.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-/**
- * Settings for the overlain views of a MapboxMap. Used by UiSettings.
- */
-class CompassViewSettings extends ViewSettings{
-
- private boolean fadeFacingNorth = true;
-
- public CompassViewSettings() {
- super();
- }
-
- public boolean isFadeFacingNorth() {
- return fadeFacingNorth;
- }
-
- public void setFadeFacingNorth(boolean fadeFacingNorth) {
- this.fadeFacingNorth = fadeFacingNorth;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java
new file mode 100644
index 0000000000..5f20155119
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java
@@ -0,0 +1,8 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.PointF;
+
+public interface FocalPointChangeListener {
+
+ void onFocalPointChanged(PointF pointF);
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
new file mode 100644
index 0000000000..0df5491535
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
@@ -0,0 +1,601 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.support.annotation.NonNull;
+import android.support.v4.view.GestureDetectorCompat;
+import android.support.v4.view.ScaleGestureDetectorCompat;
+import android.util.Log;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.ViewConfiguration;
+
+import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
+import com.almeros.android.multitouch.gesturedetectors.ShoveGestureDetector;
+import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.telemetry.MapboxEvent;
+
+import timber.log.Timber;
+
+/**
+ * Manages gestures events on a MapView.
+ * <p>
+ * Relies on gesture detection code in almeros.android.multitouch.gesturedetectors.
+ * </p>
+ */
+final class MapGestureDetector {
+
+ private final Transform transform;
+ private final Projection projection;
+ private final UiSettings uiSettings;
+ private final TrackingSettings trackingSettings;
+ private final AnnotationManager annotationManager;
+
+ private final GestureDetectorCompat gestureDetector;
+ private final ScaleGestureDetector scaleGestureDetector;
+ private final RotateGestureDetector rotateGestureDetector;
+ private final ShoveGestureDetector shoveGestureDetector;
+
+ private MapboxMap.OnMapClickListener onMapClickListener;
+ private MapboxMap.OnMapLongClickListener onMapLongClickListener;
+ private MapboxMap.OnFlingListener onFlingListener;
+ private MapboxMap.OnScrollListener onScrollListener;
+
+ private PointF focalPoint;
+
+ private boolean twoTap = false;
+ private boolean zoomStarted = false;
+ private boolean dragStarted = false;
+ private boolean quickZoom = false;
+ private boolean scrollInProgress = false;
+
+ MapGestureDetector(Context context, Transform transform, Projection projection, UiSettings uiSettings,
+ TrackingSettings trackingSettings, AnnotationManager annotationManager) {
+ this.annotationManager = annotationManager;
+ this.transform = transform;
+ this.projection = projection;
+ this.uiSettings = uiSettings;
+ this.trackingSettings = trackingSettings;
+
+ // Touch gesture detectors
+ gestureDetector = new GestureDetectorCompat(context, new GestureListener());
+ gestureDetector.setIsLongpressEnabled(true);
+ scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
+ ScaleGestureDetectorCompat.setQuickScaleEnabled(scaleGestureDetector, true);
+ rotateGestureDetector = new RotateGestureDetector(context, new RotateGestureListener());
+ shoveGestureDetector = new ShoveGestureDetector(context, new ShoveGestureListener());
+ }
+
+ /**
+ * Set the gesture focal point.
+ * <p>
+ * this is the center point used for calculate transformations from gestures, value is
+ * overridden if end user provides his own through {@link UiSettings#setFocalPoint(PointF)}.
+ * </p>
+ *
+ * @param focalPoint the center point for gestures
+ */
+ void setFocalPoint(PointF focalPoint) {
+ if (focalPoint == null) {
+ // resetting focal point,
+ if (uiSettings.getFocalPoint() != null) {
+ // using user provided one to reset
+ focalPoint = uiSettings.getFocalPoint();
+ }
+ }
+ this.focalPoint = focalPoint;
+ }
+
+
+ /**
+ * Called when user touches the screen, all positions are absolute.
+ * <p>
+ * Forwards event to the related gesture detectors.
+ * </p>
+ *
+ * @param event the MotionEvent
+ * @return True if touch event is handled
+ */
+ boolean onTouchEvent(@NonNull MotionEvent event) {
+ // Check and ignore non touch or left clicks
+ if ((event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) {
+ return false;
+ }
+
+ // Check two finger gestures first
+ rotateGestureDetector.onTouchEvent(event);
+ scaleGestureDetector.onTouchEvent(event);
+ shoveGestureDetector.onTouchEvent(event);
+
+ // Handle two finger tap
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ // First pointer down
+ transform.setGestureInProgress(true);
+ break;
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ // Second pointer down
+ twoTap = event.getPointerCount() == 2
+ && uiSettings.isZoomGesturesEnabled();
+ if (twoTap) {
+ // Confirmed 2nd Finger Down
+ MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_TWO_FINGER_SINGLETAP, event.getX(), event.getY(), transform.getZoom());
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ // Second pointer up
+ break;
+
+ case MotionEvent.ACTION_UP:
+ // First pointer up
+ long tapInterval = event.getEventTime() - event.getDownTime();
+ boolean isTap = tapInterval <= ViewConfiguration.getTapTimeout();
+ boolean inProgress = rotateGestureDetector.isInProgress()
+ || scaleGestureDetector.isInProgress()
+ || shoveGestureDetector.isInProgress();
+
+ if (twoTap && isTap && !inProgress) {
+ if (focalPoint != null) {
+ transform.zoom(false, focalPoint.x, focalPoint.y);
+ } else {
+ PointF focalPoint = TwoFingerGestureDetector.determineFocalPoint(event);
+ transform.zoom(false, focalPoint.x, focalPoint.y);
+ }
+ twoTap = false;
+ return true;
+ }
+
+ // Scroll / Pan Has Stopped
+ if (scrollInProgress) {
+ MapboxEvent.trackGestureDragEndEvent(projection, event.getX(), event.getY(), transform.getZoom());
+ scrollInProgress = false;
+ }
+
+ twoTap = false;
+ transform.setGestureInProgress(false);
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ twoTap = false;
+ transform.setGestureInProgress(false);
+ break;
+ }
+
+ return gestureDetector.onTouchEvent(event);
+ }
+
+ /**
+ * Called for events that don't fit the other handlers.
+ * <p>
+ * Examples of such events are mouse scroll events, mouse moves, joystick & trackpad.
+ * </p>
+ *
+ * @param event The MotionEvent occured
+ * @return True is the event is handled
+ */
+ boolean onGenericMotionEvent(MotionEvent event) {
+ // Mouse events
+ //if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { // this is not available before API 18
+ if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) {
+ // Choose the action
+ switch (event.getActionMasked()) {
+ // Mouse scrolls
+ case MotionEvent.ACTION_SCROLL:
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Get the vertical scroll amount, one click = 1
+ float scrollDist = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+
+ // Scale the map by the appropriate power of two factor
+ transform.zoomBy(Math.pow(2.0, scrollDist), event.getX(), event.getY());
+
+ return true;
+
+ default:
+ // We are not interested in this event
+ return false;
+ }
+ }
+
+ // We are not interested in this event
+ return false;
+ }
+
+
+ /**
+ * Responsible for handling one finger gestures.
+ */
+ private class GestureListener extends android.view.GestureDetector.SimpleOnGestureListener {
+
+ @Override
+ public boolean onDown(MotionEvent event) {
+ return true;
+ }
+
+ @Override
+ public boolean onDoubleTapEvent(MotionEvent e) {
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ switch (e.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ break;
+ case MotionEvent.ACTION_MOVE:
+ break;
+ case MotionEvent.ACTION_UP:
+ if (quickZoom) {
+ // insert here?
+ quickZoom = false;
+ break;
+ }
+
+ // Single finger double tap
+ if (focalPoint != null) {
+ // User provided focal point
+ transform.zoom(true, focalPoint.x, focalPoint.y);
+ } else {
+ // Zoom in on gesture
+ transform.zoom(true, e.getX(), e.getY());
+ }
+ break;
+ }
+
+ MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_DOUBLETAP, e.getX(), e.getY(), transform.getZoom());
+
+ return true;
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent motionEvent) {
+ // Cancel any animation
+ transform.cancelTransitions();
+ return true;
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
+ PointF tapPoint = new PointF(motionEvent.getX(), motionEvent.getY());
+ boolean tapHandled = annotationManager.onTap(tapPoint, uiSettings.getPixelRatio());
+
+ if (!tapHandled) {
+ if (uiSettings.isDeselectMarkersOnTap()) {
+ // deselect any selected marker
+ annotationManager.deselectMarkers();
+ }
+
+ // notify app of map click
+ if (onMapClickListener != null) {
+ onMapClickListener.onMapClick(projection.fromScreenLocation(tapPoint));
+ }
+ }
+
+ MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_SINGLETAP, motionEvent.getX(), motionEvent.getY(), transform.getZoom());
+ return true;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent motionEvent) {
+ if (onMapLongClickListener != null && !quickZoom) {
+ onMapLongClickListener.onMapLongClick(projection.fromScreenLocation(new PointF(motionEvent.getX(), motionEvent.getY())));
+ }
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ trackingSettings.resetTrackingModesIfRequired(true, false);
+
+ double decelerationRate = 1;
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ float screenDensity = uiSettings.getPixelRatio();
+ double offsetX = velocityX * decelerationRate / 4 / screenDensity;
+ double offsetY = velocityY * decelerationRate / 4 / screenDensity;
+
+ transform.setGestureInProgress(true);
+ transform.moveBy(offsetX, offsetY, (long) (decelerationRate * 1000.0f));
+ transform.setGestureInProgress(false);
+
+ if (onFlingListener != null) {
+ onFlingListener.onFling();
+ }
+
+ MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_PAN_START, e1.getX(), e1.getY(), transform.getZoom());
+ return true;
+ }
+
+ // Called for drags
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ if (!scrollInProgress) {
+ scrollInProgress = true;
+ }
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ if (dragStarted) {
+ return false;
+ }
+
+ // reset tracking if needed
+ trackingSettings.resetTrackingModesIfRequired(true, false);
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Scroll the map
+ transform.moveBy(-distanceX, -distanceY, 0 /*no duration*/);
+
+ if (onScrollListener != null) {
+ onScrollListener.onScroll();
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Responsible for handling two finger gestures and double-tap drag gestures.
+ */
+ private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+
+ long beginTime = 0;
+ float scaleFactor = 1.0f;
+
+ // Called when two fingers first touch the screen
+ @Override
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ beginTime = detector.getEventTime();
+ MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_PINCH_START, detector.getFocusX(), detector.getFocusY(), transform.getZoom());
+ return true;
+ }
+
+ // Called when fingers leave screen
+ @Override
+ public void onScaleEnd(ScaleGestureDetector detector) {
+ beginTime = 0;
+ scaleFactor = 1.0f;
+ zoomStarted = false;
+ }
+
+ // Called each time a finger moves
+ // Called for pinch zooms and quickzooms/quickscales
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return super.onScale(detector);
+ }
+
+ // If scale is large enough ignore a tap
+ scaleFactor *= detector.getScaleFactor();
+ if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) {
+ zoomStarted = true;
+ }
+
+ // Ignore short touches in case it is a tap
+ // Also ignore small scales
+ long time = detector.getEventTime();
+ long interval = time - beginTime;
+ if (!zoomStarted && (interval <= ViewConfiguration.getTapTimeout())) {
+ return false;
+ }
+
+ if (!zoomStarted) {
+ return false;
+ }
+
+ if (dragStarted) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Gesture is a quickzoom if there aren't two fingers
+ quickZoom = !twoTap;
+
+ // make an assumption here; if the zoom center is specified by the gesture, it's NOT going
+ // to be in the center of the map. Therefore the zoom will translate the map center, so tracking
+ // should be disabled.
+
+ trackingSettings.resetTrackingModesIfRequired(!quickZoom, false);
+ // Scale the map
+ if (focalPoint != null) {
+ // arround user provided focal point
+ transform.zoomBy(detector.getScaleFactor(), focalPoint.x, focalPoint.y);
+ } else if (quickZoom) {
+ // around center map
+ transform.zoomBy(detector.getScaleFactor(), uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ } else {
+ // around gesture
+ transform.zoomBy(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY());
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Responsible for handling rotation gestures.
+ */
+ private class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
+
+ long beginTime = 0;
+ float totalAngle = 0.0f;
+ boolean started = false;
+
+ // Called when two fingers first touch the screen
+ @Override
+ public boolean onRotateBegin(RotateGestureDetector detector) {
+ if (!trackingSettings.isRotateGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ beginTime = detector.getEventTime();
+ MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_ROTATION_START, detector.getFocusX(), detector.getFocusY(), transform.getZoom());
+ return true;
+ }
+
+ // Called when the fingers leave the screen
+ @Override
+ public void onRotateEnd(RotateGestureDetector detector) {
+ beginTime = 0;
+ totalAngle = 0.0f;
+ started = false;
+ }
+
+ // Called each time one of the two fingers moves
+ // Called for rotation
+ @Override
+ public boolean onRotate(RotateGestureDetector detector) {
+ if (!trackingSettings.isRotateGestureCurrentlyEnabled() || dragStarted) {
+ return false;
+ }
+
+ // If rotate is large enough ignore a tap
+ // Also is zoom already started, don't rotate
+ totalAngle += detector.getRotationDegreesDelta();
+ if (!zoomStarted && ((totalAngle > 20.0f) || (totalAngle < -20.0f))) {
+ started = true;
+ }
+
+ // Ignore short touches in case it is a tap
+ // Also ignore small rotate
+ long time = detector.getEventTime();
+ long interval = time - beginTime;
+ if (!started && (interval <= ViewConfiguration.getTapTimeout())) {
+ return false;
+ }
+
+ if (!started) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // rotation constitutes translation of anything except the center of
+ // rotation, so cancel both location and bearing tracking if required
+
+ trackingSettings.resetTrackingModesIfRequired(true, true);
+
+ // Get rotate value
+ double bearing = transform.getRawBearing();
+ bearing += detector.getRotationDegreesDelta();
+
+ // Rotate the map
+ if (focalPoint != null) {
+ // User provided focal point
+ transform.setBearing(bearing, focalPoint.x, focalPoint.y);
+ } else {
+ // around gesture
+ transform.setBearing(bearing, detector.getFocusX(), detector.getFocusY());
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Responsible for handling 2 finger shove gestures.
+ */
+ private class ShoveGestureListener implements ShoveGestureDetector.OnShoveGestureListener {
+
+ long beginTime = 0;
+ float totalDelta = 0.0f;
+ boolean started = false;
+
+ @Override
+ public boolean onShoveBegin(ShoveGestureDetector detector) {
+ if (!uiSettings.isTiltGesturesEnabled()) {
+ return false;
+ }
+
+ beginTime = detector.getEventTime();
+ MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_PITCH_START, detector.getFocusX(), detector.getFocusY(), transform.getZoom());
+ return true;
+ }
+
+ @Override
+ public void onShoveEnd(ShoveGestureDetector detector) {
+ beginTime = 0;
+ totalDelta = 0.0f;
+ started = false;
+ dragStarted = false;
+ }
+
+ @Override
+ public boolean onShove(ShoveGestureDetector detector) {
+ if (!uiSettings.isTiltGesturesEnabled()) {
+ return false;
+ }
+
+ // If tilt is large enough ignore a tap
+ // Also if zoom already started, don't tilt
+ totalDelta += detector.getShovePixelsDelta();
+ if (!zoomStarted && ((totalDelta > 10.0f) || (totalDelta < -10.0f))) {
+ started = true;
+ }
+
+ // Ignore short touches in case it is a tap
+ // Also ignore small tilt
+ long time = detector.getEventTime();
+ long interval = time - beginTime;
+ if (!started && (interval <= ViewConfiguration.getTapTimeout())) {
+ return false;
+ }
+
+ if (!started) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Get tilt value (scale and clamp)
+ double pitch = transform.getTilt();
+ pitch -= 0.1 * detector.getShovePixelsDelta();
+ pitch = Math.max(MapboxConstants.MINIMUM_TILT, Math.min(MapboxConstants.MAXIMUM_TILT, pitch));
+
+ // Tilt the map
+ transform.setTilt(pitch);
+
+ dragStarted = true;
+
+ return true;
+ }
+ }
+
+ void setOnMapClickListener(MapboxMap.OnMapClickListener onMapClickListener) {
+ this.onMapClickListener = onMapClickListener;
+ }
+
+ void setOnMapLongClickListener(MapboxMap.OnMapLongClickListener onMapLongClickListener) {
+ this.onMapLongClickListener = onMapLongClickListener;
+ }
+
+ void setOnFlingListener(MapboxMap.OnFlingListener onFlingListener) {
+ this.onFlingListener = onFlingListener;
+ }
+
+ void setOnScrollListener(MapboxMap.OnScrollListener onScrollListener) {
+ this.onScrollListener = onScrollListener;
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java
new file mode 100644
index 0000000000..09b4a2c9ca
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java
@@ -0,0 +1,264 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+/**
+ * Manages key events on a MapView.
+ * <p>
+ * <ul>
+ * <li> Uses {@link Transform} to change the map state</li>
+ * <li> Uses {@link TrackingSettings} to verify validity of the current tracking mode.</li>
+ * <li> Uses {@link UiSettings} to verify validity of user restricted movement.</li>
+ * </ul>
+ * <p>
+ */
+final class MapKeyListener {
+
+ private final TrackingSettings trackingSettings;
+ private final Transform transform;
+ private final UiSettings uiSettings;
+
+ private TrackballLongPressTimeOut currentTrackballLongPressTimeOut;
+
+ MapKeyListener(@NonNull Transform transform, @NonNull TrackingSettings trackingSettings, @NonNull UiSettings uiSettings) {
+ this.transform = transform;
+ this.trackingSettings = trackingSettings;
+ this.uiSettings = uiSettings;
+ }
+
+ /**
+ * Called when the user presses a key, alse called for repeated keys held down.
+ *
+ * @param keyCode the id of the pressed key
+ * @param event the related key event
+ * @return true if the wevent is handled
+ */
+ boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
+ // If the user has held the scroll key down for a while then accelerate
+ // the scroll speed
+ double scrollDist = event.getRepeatCount() >= 5 ? 50.0 : 10.0;
+
+ // Check which key was pressed via hardware/real key code
+ switch (keyCode) {
+ // Tell the system to track these keys for long presses on
+ // onKeyLongPress is fired
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ event.startTracking();
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Move left
+ transform.moveBy(scrollDist, 0.0, 0 /*no animation*/);
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Move right
+ transform.moveBy(-scrollDist, 0.0, 0 /*no animation*/);
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Move up
+ transform.moveBy(0.0, scrollDist, 0 /*no animation*/);
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Move down
+ transform.moveBy(0.0, -scrollDist, 0 /*no animation*/);
+ return true;
+
+ default:
+ // We are not interested in this key
+ return false;
+ }
+ }
+
+ /**
+ * Called when the user long presses a key that is being tracked.
+ *
+ * @param keyCode the id of the long pressed key
+ * @param event the related key event
+ * @return true if event is handled
+ */
+ boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ // Check which key was pressed via hardware/real key code
+ switch (keyCode) {
+ // Tell the system to track these keys for long presses on
+ // onKeyLongPress is fired
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ // Zoom out
+ transform.zoom(false, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ return true;
+
+ default:
+ // We are not interested in this key
+ return false;
+ }
+ }
+
+ /**
+ * Called when the user releases a key.
+ *
+ * @param keyCode the id of the released key
+ * @param event the related key event
+ * @return true if the event is handled
+ */
+ boolean onKeyUp(int keyCode, KeyEvent event) {
+ // Check if the key action was canceled (used for virtual keyboards)
+ if (event.isCanceled()) {
+ return false;
+ }
+
+ // Check which key was pressed via hardware/real key code
+ // Note if keyboard does not have physical key (ie primary non-shifted
+ // key) then it will not appear here
+ // Must use the key character map as physical to character is not
+ // fixed/guaranteed
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ // Zoom in
+ transform.zoom(true, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ return true;
+ }
+
+ // We are not interested in this key
+ return false;
+ }
+
+ /**
+ * Called for trackball events, all motions are relative in device specific units.
+ *
+ * @param event the related motion event
+ * @return true if the event is handled
+ */
+ boolean onTrackballEvent(MotionEvent event) {
+ // Choose the action
+ switch (event.getActionMasked()) {
+ // The trackball was rotated
+ case MotionEvent.ACTION_MOVE:
+ if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ return false;
+ }
+
+ // Cancel any animation
+ transform.cancelTransitions();
+
+ // Scroll the map
+ transform.moveBy(-10.0 * event.getX(), -10.0 * event.getY(), 0 /*no animation*/);
+ return true;
+
+ // Trackball was pushed in so start tracking and tell system we are
+ // interested
+ // We will then get the up action
+ case MotionEvent.ACTION_DOWN:
+ // Set up a delayed callback to check if trackball is still
+ // After waiting the system long press time out
+ if (currentTrackballLongPressTimeOut != null) {
+ currentTrackballLongPressTimeOut.cancel();
+ currentTrackballLongPressTimeOut = null;
+ }
+ currentTrackballLongPressTimeOut = new TrackballLongPressTimeOut();
+ new Handler().postDelayed(currentTrackballLongPressTimeOut,
+ ViewConfiguration.getLongPressTimeout());
+ return true;
+
+ // Trackball was released
+ case MotionEvent.ACTION_UP:
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return false;
+ }
+
+ // Only handle if we have not already long pressed
+ if (currentTrackballLongPressTimeOut != null) {
+ // Zoom in
+ transform.zoom(true, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ }
+ return true;
+
+ // Trackball was cancelled
+ case MotionEvent.ACTION_CANCEL:
+ if (currentTrackballLongPressTimeOut != null) {
+ currentTrackballLongPressTimeOut.cancel();
+ currentTrackballLongPressTimeOut = null;
+ }
+ return true;
+
+ default:
+ // We are not interested in this event
+ return false;
+ }
+ }
+
+ /**
+ * This class implements the trackball long press time out callback
+ */
+ private class TrackballLongPressTimeOut implements Runnable {
+
+ // Track if we have been cancelled
+ private boolean cancelled;
+
+ TrackballLongPressTimeOut() {
+ cancelled = false;
+ }
+
+ // Cancel the timeout
+ public void cancel() {
+ cancelled = true;
+ }
+
+ // Called when long press time out expires
+ @Override
+ public void run() {
+ // Check if the trackball is still pressed
+ if (!cancelled) {
+ // Zoom out
+ transform.zoom(false, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+
+ // Ensure the up action is not run
+ currentTrackballLongPressTimeOut = null;
+ }
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
index 3fe9a67f3c..cd7caf395d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
@@ -1,7 +1,5 @@
package com.mapbox.mapboxsdk.maps;
-import android.Manifest;
-import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.app.Fragment;
@@ -11,66 +9,47 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.PointF;
-import android.graphics.RectF;
import android.graphics.SurfaceTexture;
-import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.CallSuper;
-import android.support.annotation.FloatRange;
import android.support.annotation.IntDef;
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.view.GestureDetectorCompat;
-import android.support.v4.view.ScaleGestureDetectorCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.AttributeSet;
-import timber.log.Timber;
-import android.view.GestureDetector;
-import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ZoomButtonsController;
-import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
-import com.almeros.android.multitouch.gesturedetectors.ShoveGestureDetector;
-import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
import com.mapbox.mapboxsdk.MapboxAccountManager;
import com.mapbox.mapboxsdk.R;
-import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
-import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.constants.Style;
-import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.LocationListener;
import com.mapbox.mapboxsdk.location.LocationServices;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
@@ -78,17 +57,15 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.telemetry.MapboxEvent;
import com.mapbox.mapboxsdk.telemetry.MapboxEventManager;
-import com.mapbox.mapboxsdk.utils.ColorUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
-import static com.mapbox.mapboxsdk.utils.MathUtils.convertNativeBearing;
+import timber.log.Timber;
/**
* <p>
@@ -107,8 +84,6 @@ import static com.mapbox.mapboxsdk.utils.MathUtils.convertNativeBearing;
public class MapView extends FrameLayout {
private MapboxMap mapboxMap;
- private IconManager iconManager;
- private AnnotationManager annotationManager;
private boolean initialLoad;
private boolean destroyed;
@@ -116,42 +91,18 @@ public class MapView extends FrameLayout {
private NativeMapView nativeMapView;
private boolean hasSurface = false;
- private ViewGroup markerViewContainer;
private CompassView compassView;
- private ImageView logoView;
- private ImageView attributionsView;
private MyLocationView myLocationView;
private LocationListener myLocationListener;
- private Projection projection;
+ private MapGestureDetector mapGestureDetector;
+ private MapKeyListener mapKeyListener;
- private ZoomButtonsController zoomButtonsController;
private ConnectivityReceiver connectivityReceiver;
- private float screenDensity = 1.0f;
-
- private TrackballLongPressTimeOut currentTrackballLongPressTimeOut;
- private GestureDetectorCompat gestureDetector;
- private ScaleGestureDetector scaleGestureDetector;
- private RotateGestureDetector rotateGestureDetector;
- private ShoveGestureDetector shoveGestureDetector;
- private boolean twoTap = false;
- private boolean zoomStarted = false;
- private boolean dragStarted = false;
- private boolean quickZoom = false;
- private boolean scrollInProgress = false;
-
- private int contentPaddingLeft;
- private int contentPaddingTop;
- private int contentPaddingRight;
- private int contentPaddingBottom;
-
- private PointF focalPoint;
-
- private String styleUrl = Style.MAPBOX_STREETS;
- private boolean styleWasSet = false;
-
- private List<OnMapReadyCallback> onMapReadyCallbackList;
+
+ private List<OnMapReadyCallback> onMapReadyCallbackList = new ArrayList<>();
private SnapshotRequest snapshotRequest;
+ private ZoomButtonsController zoomButtonsController;
private boolean onStartCalled;
private boolean onStopCalled;
@@ -175,21 +126,20 @@ public class MapView extends FrameLayout {
}
@UiThread
- public MapView(@NonNull Context context, @Nullable MapboxMapOptions options) {
+ public MapView(@NonNull Context context, @NonNull MapboxMapOptions options) {
super(context);
initialize(context, options);
}
- private void initialize(@NonNull Context context, @NonNull MapboxMapOptions options) {
+ private void initialize(@NonNull final Context context, @NonNull final MapboxMapOptions options) {
if (isInEditMode()) {
// if we are in an editor mode we show an image of a map
LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_preview, this);
return;
}
+ // TODO distill into singular purpose methods/classes
initialLoad = true;
- onMapReadyCallbackList = new ArrayList<>();
-
View view = LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this);
setWillNotDraw(false);
@@ -204,153 +154,61 @@ public class MapView extends FrameLayout {
}
nativeMapView = new NativeMapView(this);
- iconManager = new IconManager(nativeMapView);
- mapboxMap = new MapboxMap(this, iconManager);
- annotationManager = mapboxMap.getAnnotationManager();
- projection = mapboxMap.getProjection();
+
+ // inflate overlain Views
+ compassView = (CompassView) view.findViewById(R.id.compassView);
+ myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView);
+ ImageView logoView = (ImageView) view.findViewById(R.id.logoView);
+ ImageView attributionsView = (ImageView) view.findViewById(R.id.attributionView);
+ attributionsView.setOnClickListener(new AttributionOnClickListener(this));
+ ViewGroup markerViewContainer = (ViewGroup) findViewById(R.id.markerViewContainer);
+
+ // interface for focal point invalidation
+ FocalPointInvalidator focalPointInvalidator = new FocalPointInvalidator();
+
+ // interface for registering touch listeners
+ RegisterTouchListener registerTouchListener = new RegisterTouchListener();
+
+ // setup components for MapboxMap creation
+ Projection projection = new Projection(nativeMapView);
+ UiSettings uiSettings = new UiSettings(projection, focalPointInvalidator, compassView, attributionsView, logoView);
+ TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPointInvalidator);
+ MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(projection, myLocationView, trackingSettings);
+ MarkerViewManager markerViewManager = new MarkerViewManager(markerViewContainer);
+ AnnotationManager annotationManager = new AnnotationManager(nativeMapView, this, markerViewManager);
+ Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings);
+ mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, projection, registerTouchListener, annotationManager);
+
+ // active user input
+ mapGestureDetector = new MapGestureDetector(context, mapboxMap.getTransform(), projection, uiSettings, trackingSettings, annotationManager);
+ mapKeyListener = new MapKeyListener(mapboxMap.getTransform(), trackingSettings, uiSettings);
+
+ // attach widgets to MapboxMap
+ compassView.setMapboxMap(mapboxMap);
+ myLocationView.setMapboxMap(mapboxMap);
// Ensure this view is interactable
setClickable(true);
setLongClickable(true);
setFocusable(true);
setFocusableInTouchMode(true);
+ requestDisallowInterceptTouchEvent(true);
requestFocus();
- // Touch gesture detectors
- gestureDetector = new GestureDetectorCompat(context, new GestureListener());
- gestureDetector.setIsLongpressEnabled(true);
- scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
- ScaleGestureDetectorCompat.setQuickScaleEnabled(scaleGestureDetector, true);
- rotateGestureDetector = new RotateGestureDetector(context, new RotateGestureListener());
- shoveGestureDetector = new ShoveGestureDetector(context, new ShoveGestureListener());
-
- zoomButtonsController = new ZoomButtonsController(this);
- zoomButtonsController.setZoomSpeed(MapboxConstants.ANIMATION_DURATION);
- zoomButtonsController.setOnZoomListener(new OnZoomListener());
-
// Connectivity
onConnectivityChanged(isConnected());
- markerViewContainer = (ViewGroup) view.findViewById(R.id.markerViewContainer);
-
- myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView);
- myLocationView.setMapboxMap(mapboxMap);
-
- compassView = (CompassView) view.findViewById(R.id.compassView);
- compassView.setMapboxMap(mapboxMap);
-
- logoView = (ImageView) view.findViewById(R.id.logoView);
-
- // Setup Attributions control
- attributionsView = (ImageView) view.findViewById(R.id.attributionView);
- attributionsView.setOnClickListener(new AttributionOnClickListener(this));
-
- screenDensity = context.getResources().getDisplayMetrics().density;
+ // configure the zoom button controller
+ zoomButtonsController = new ZoomButtonsController(MapView.this);
+ zoomButtonsController.setZoomSpeed(MapboxConstants.ANIMATION_DURATION);
+ zoomButtonsController.setOnZoomListener(new OnZoomListener(mapboxMap));
- setInitialState(options);
+ mapboxMap.initialise(context, options);
// Shows the zoom controls
if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) {
- mapboxMap.getUiSettings().setZoomControlsEnabled(true);
- }
- }
-
- private void setInitialState(MapboxMapOptions options) {
- mapboxMap.setDebugActive(options.getDebugActive());
-
- CameraPosition position = options.getCamera();
- if (position != null && !position.equals(CameraPosition.DEFAULT)) {
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(position));
- myLocationView.setTilt(position.tilt);
- }
-
- // api base url
- String apiBaseUrl = options.getApiBaseUrl();
- if (!TextUtils.isEmpty(apiBaseUrl)) {
- setApiBaseUrl(apiBaseUrl);
- }
-
- // access token
- String accessToken = options.getAccessToken();
- if (!TextUtils.isEmpty(accessToken)) {
- mapboxMap.setAccessToken(accessToken);
- }
-
- // style url
- String style = options.getStyle();
- if (!TextUtils.isEmpty(style)) {
- styleUrl = style;
- }
-
- // MyLocationView
- MyLocationViewSettings myLocationViewSettings = mapboxMap.getMyLocationViewSettings();
- myLocationViewSettings.setForegroundDrawable(
- options.getMyLocationForegroundDrawable(), options.getMyLocationForegroundBearingDrawable());
- myLocationViewSettings.setForegroundTintColor(options.getMyLocationForegroundTintColor());
- myLocationViewSettings.setBackgroundDrawable(
- options.getMyLocationBackgroundDrawable(), options.getMyLocationBackgroundPadding());
- myLocationViewSettings.setBackgroundTintColor(options.getMyLocationBackgroundTintColor());
- myLocationViewSettings.setAccuracyAlpha(options.getMyLocationAccuracyAlpha());
- myLocationViewSettings.setAccuracyTintColor(options.getMyLocationAccuracyTintColor());
- mapboxMap.setMyLocationEnabled(options.getLocationEnabled());
-
- // Enable gestures
- UiSettings uiSettings = mapboxMap.getUiSettings();
- uiSettings.setZoomGesturesEnabled(options.getZoomGesturesEnabled());
- uiSettings.setZoomGestureChangeAllowed(options.getZoomGesturesEnabled());
- uiSettings.setScrollGesturesEnabled(options.getScrollGesturesEnabled());
- uiSettings.setScrollGestureChangeAllowed(options.getScrollGesturesEnabled());
- uiSettings.setRotateGesturesEnabled(options.getRotateGesturesEnabled());
- uiSettings.setRotateGestureChangeAllowed(options.getRotateGesturesEnabled());
- uiSettings.setTiltGesturesEnabled(options.getTiltGesturesEnabled());
- uiSettings.setTiltGestureChangeAllowed(options.getTiltGesturesEnabled());
-
- // Ui Controls
- uiSettings.setZoomControlsEnabled(options.getZoomControlsEnabled());
-
- // Zoom
- mapboxMap.setMaxZoom(options.getMaxZoom());
- mapboxMap.setMinZoom(options.getMinZoom());
-
- // Compass
- uiSettings.setCompassEnabled(options.getCompassEnabled());
- uiSettings.setCompassGravity(options.getCompassGravity());
- int[] compassMargins = options.getCompassMargins();
- if (compassMargins != null) {
- uiSettings.setCompassMargins(compassMargins[0], compassMargins[1], compassMargins[2], compassMargins[3]);
- } else {
- int tenDp = (int) getResources().getDimension(R.dimen.mapbox_ten_dp);
- uiSettings.setCompassMargins(tenDp, tenDp, tenDp, tenDp);
- }
- uiSettings.setCompassFadeFacingNorth(options.getCompassFadeFacingNorth());
-
- // Logo
- uiSettings.setLogoEnabled(options.getLogoEnabled());
- uiSettings.setLogoGravity(options.getLogoGravity());
- int[] logoMargins = options.getLogoMargins();
- if (logoMargins != null) {
- uiSettings.setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]);
- } else {
- int sixteenDp = (int) getResources().getDimension(R.dimen.mapbox_sixteen_dp);
- uiSettings.setLogoMargins(sixteenDp, sixteenDp, sixteenDp, sixteenDp);
- }
-
- // Attribution
- uiSettings.setAttributionEnabled(options.getAttributionEnabled());
- uiSettings.setAttributionGravity(options.getAttributionGravity());
- int[] attributionMargins = options.getAttributionMargins();
- if (attributionMargins != null) {
- uiSettings.setAttributionMargins(attributionMargins[0], attributionMargins[1], attributionMargins[2], attributionMargins[3]);
- } else {
- Resources resources = getResources();
- int sevenDp = (int) resources.getDimension(R.dimen.mapbox_seven_dp);
- int seventySixDp = (int) resources.getDimension(R.dimen.mapbox_seventy_six_dp);
- uiSettings.setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp);
+ uiSettings.setZoomControlsEnabled(true);
}
-
- int attributionTintColor = options.getAttributionTintColor();
- uiSettings.setAttributionTintColor(attributionTintColor != -1
- ? attributionTintColor : ColorUtils.getPrimaryColor(getContext()));
}
//
@@ -370,17 +228,20 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onCreate(@Nullable Bundle savedInstanceState) {
+ // TODO distill into singular purpose methods/classes
String accessToken = mapboxMap.getAccessToken();
if (TextUtils.isEmpty(accessToken)) {
accessToken = MapboxAccountManager.getInstance().getAccessToken();
- mapboxMap.setAccessToken(accessToken);
+ nativeMapView.setAccessToken(accessToken);
} else {
// user provided access token through xml attributes, need to start MapboxAccountManager
MapboxAccountManager.start(getContext(), accessToken);
+ nativeMapView.setAccessToken(accessToken);
}
// Force a check for an access token
MapboxAccountManager.validateAccessToken(accessToken);
+ nativeMapView.setAccessToken(accessToken);
if (savedInstanceState != null && savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) {
@@ -427,7 +288,11 @@ public class MapView extends FrameLayout {
, savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM));
mapboxMap.setDebugActive(savedInstanceState.getBoolean(MapboxConstants.STATE_DEBUG_ACTIVE));
- styleUrl = savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL);
+
+ String styleUrl = savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL);
+ if (!TextUtils.isEmpty(styleUrl)) {
+ nativeMapView.setStyleUrl(savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL));
+ }
// User location
try {
@@ -462,11 +327,12 @@ public class MapView extends FrameLayout {
addOnMapChangedListener(new OnMapChangedListener() {
@Override
public void onMapChanged(@MapChange int change) {
+
+ // TODO extract logic into separate OnMapReady and Update Component
if (change == DID_FINISH_LOADING_STYLE && initialLoad) {
initialLoad = false;
- iconManager.reloadIcons();
- annotationManager.reloadMarkers();
- annotationManager.adjustTopOffsetPixels(mapboxMap);
+ mapboxMap.getAnnotationManager().reloadMarkers();
+ mapboxMap.getAnnotationManager().adjustTopOffsetPixels(mapboxMap);
// Notify listeners the map is ready
if (onMapReadyCallbackList.size() > 0) {
@@ -484,7 +350,7 @@ public class MapView extends FrameLayout {
} else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) {
mapboxMap.getMarkerViewManager().scheduleViewMarkerInvalidation();
- compassView.update(getDirection());
+ compassView.update(mapboxMap.getTransform().getBearing());
myLocationView.update();
mapboxMap.getMarkerViewManager().update();
@@ -517,7 +383,7 @@ public class MapView extends FrameLayout {
outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true);
outState.putParcelable(MapboxConstants.STATE_CAMERA_POSITION, mapboxMap.getCameraPosition());
outState.putBoolean(MapboxConstants.STATE_DEBUG_ACTIVE, mapboxMap.isDebugActive());
- outState.putString(MapboxConstants.STATE_STYLE_URL, styleUrl);
+ outState.putString(MapboxConstants.STATE_STYLE_URL, nativeMapView.getStyleUrl());
outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED, mapboxMap.isMyLocationEnabled());
// TrackingSettings
@@ -579,9 +445,9 @@ public class MapView extends FrameLayout {
nativeMapView.update();
myLocationView.onStart();
- // In case that no style was set or was loaded through MapboxMapOptions
- if (!styleWasSet) {
- setStyleUrl(styleUrl);
+ if (TextUtils.isEmpty(nativeMapView.getStyleUrl())) {
+ // if user hasn't loaded a Style yet, load default for them instead
+ nativeMapView.setStyleUrl(Style.MAPBOX_STREETS);
}
}
@@ -640,16 +506,63 @@ public class MapView extends FrameLayout {
nativeMapView = null;
}
- void setFocalPoint(PointF focalPoint) {
- if (focalPoint == null) {
- // resetting focal point,
- UiSettings uiSettings = mapboxMap.getUiSettings();
- // need to validate if we need to reset focal point with user provided one
- if (uiSettings.getFocalPoint() != null) {
- focalPoint = uiSettings.getFocalPoint();
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
+ zoomButtonsController.setVisible(true);
}
}
- this.focalPoint = focalPoint;
+ return mapGestureDetector.onTouchEvent(event) || super.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return mapKeyListener.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ return mapKeyListener.onKeyLongPress(keyCode, event) || super.onKeyLongPress(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return mapKeyListener.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ return mapKeyListener.onTrackballEvent(event) || super.onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ return mapGestureDetector.onGenericMotionEvent(event) || super.onGenericMotionEvent(event);
+ }
+
+ @Override
+ public boolean onHoverEvent(MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ case MotionEvent.ACTION_HOVER_MOVE:
+ // Show the zoom controls
+ if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
+ zoomButtonsController.setVisible(true);
+ }
+ return true;
+
+ case MotionEvent.ACTION_HOVER_EXIT:
+ // Hide the zoom controls
+ if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
+ zoomButtonsController.setVisible(false);
+ }
+ return true;
+
+ default:
+ // We are not interested in this event
+ return false;
+ }
}
/**
@@ -675,179 +588,6 @@ public class MapView extends FrameLayout {
});
}
- //
- // LatLng / CenterCoordinate
- //
-
- LatLng getLatLng() {
- return nativeMapView.getLatLng();
- }
-
- //
- // Pitch / Tilt
- //
-
- double getTilt() {
- return nativeMapView.getPitch();
- }
-
- void setTilt(Double pitch) {
- mapboxMap.getMarkerViewManager().setTilt(pitch.floatValue());
- myLocationView.setTilt(pitch);
- nativeMapView.setPitch(pitch, 0);
- }
-
- //
- // Center coordinate
- //
-
- LatLng getCenterCoordinate() {
- return nativeMapView.getLatLng();
- }
-
- void setCenterCoordinate(LatLng centerCoordinate) {
- nativeMapView.setLatLng(centerCoordinate);
- }
-
- //
- // Direction
- //
-
- double getDirection() {
- if (destroyed) {
- return 0;
- }
-
- return convertNativeBearing(nativeMapView.getBearing());
- }
-
- void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction) {
- if (destroyed) {
- return;
- }
- setDirection(direction, false);
- }
-
- void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction, boolean animated) {
- if (destroyed) {
- return;
- }
- long duration = animated ? MapboxConstants.ANIMATION_DURATION : 0;
- mapboxMap.cancelTransitions();
- // Out of range directions are normalised in setBearing
- nativeMapView.setBearing(-direction, duration);
- }
-
- void resetNorth() {
- if (destroyed) {
- return;
- }
- myLocationView.setBearing(0);
- mapboxMap.cancelTransitions();
- nativeMapView.resetNorth();
- }
-
- //
- // Content padding
- //
-
- int getContentPaddingLeft() {
- return contentPaddingLeft;
- }
-
- int getContentPaddingTop() {
- return contentPaddingTop;
- }
-
- int getContentPaddingRight() {
- return contentPaddingRight;
- }
-
- int getContentPaddingBottom() {
- return contentPaddingBottom;
- }
-
- //
- // Zoom
- //
-
- double getZoom() {
- if (destroyed) {
- return 0;
- }
- return nativeMapView.getZoom();
- }
-
- void setMinZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) {
- if (destroyed) {
- return;
- }
- nativeMapView.setMinZoom(minZoom);
- }
-
- double getMinZoom() {
- if (destroyed) {
- return 0;
- }
- return nativeMapView.getMinZoom();
- }
-
- void setMaxZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) {
- if (destroyed) {
- return;
- }
- nativeMapView.setMaxZoom(maxZoom);
- }
-
- double getMaxZoom() {
- if (destroyed) {
- return 0;
- }
- return nativeMapView.getMaxZoom();
- }
-
- // Zoom in or out
- private void zoom(boolean zoomIn) {
- zoom(zoomIn, -1.0f, -1.0f);
- }
-
- private void zoom(boolean zoomIn, float x, float y) {
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- if (zoomIn) {
- nativeMapView.scaleBy(2.0, x / screenDensity, y / screenDensity, MapboxConstants.ANIMATION_DURATION);
- } else {
- nativeMapView.scaleBy(0.5, x / screenDensity, y / screenDensity, MapboxConstants.ANIMATION_DURATION);
- }
- }
-
- //
- // Debug
- //
-
- boolean isDebugActive() {
- return !destroyed && nativeMapView.getDebug();
- }
-
- void setDebugActive(boolean debugActive) {
- if (destroyed) {
- return;
- }
- nativeMapView.setDebug(debugActive);
- }
-
- void cycleDebugOptions() {
- if (destroyed) {
- return;
- }
- nativeMapView.cycleDebugOptions();
- }
-
- //
- // Styling
- //
-
/**
* <p>
* Loads a new map style from the specified URL.
@@ -886,57 +626,9 @@ public class MapView extends FrameLayout {
setAccessToken(MapboxAccountManager.getInstance().getAccessToken());
}
- styleUrl = url;
nativeMapView.setStyleUrl(url);
- styleWasSet = true;
- }
-
- /**
- * <p>
- * Loads a new map style from the specified bundled style.
- * </p>
- * <p>
- * This method is asynchronous and will return immediately before the style finishes loading.
- * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event.
- * </p>
- * If the style fails to load or an invalid style URL is set, the map view will become blank.
- * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be sent.
- *
- * @param style The bundled style. Accepts one of the values from {@link Style}.
- * @see Style
- */
- @UiThread
- public void setStyle(@Style.StyleUrl String style) {
- setStyleUrl(style);
- }
-
- /**
- * <p>
- * Returns the map style currently displayed in the map view.
- * </p>
- * If the default style is currently displayed, a URL will be returned instead of null.
- *
- * @return The URL of the map style.
- */
- @UiThread
- @NonNull
- public String getStyleUrl() {
- return styleUrl;
}
- //
- // API Base URL
- //
-
- @UiThread
- void setApiBaseUrl(@NonNull String baseUrl) {
- nativeMapView.setApiBaseUrl(baseUrl);
- }
-
- //
- // Access token
- //
-
/**
* <p>
* DEPRECATED @see MapboxAccountManager#start(String)
@@ -989,78 +681,6 @@ public class MapView extends FrameLayout {
}
//
- // Projection
- //
-
- /*
- * Internal use only, use Projection#fromScreenLocation instead
- */
- LatLng fromNativeScreenLocation(@NonNull PointF point) {
- if (destroyed) {
- return new LatLng();
- }
- return nativeMapView.latLngForPixel(point);
- }
-
- /*
- * Internal use only, use Projection#toScreenLocation instead.
- */
- PointF toNativeScreenLocation(@NonNull LatLng location) {
- if (destroyed || location == null) {
- return new PointF();
- }
- return nativeMapView.pixelForLatLng(location);
- }
-
- /**
- * @return the ViewGroup containing the marker views
- */
- public ViewGroup getMarkerViewContainer() {
- return markerViewContainer;
- }
-
- void setContentPadding(int left, int top, int right, int bottom) {
- if (destroyed) {
- return;
- }
-
-// if (left == contentPaddingLeft && top == contentPaddingTop && right == contentPaddingRight && bottom == contentPaddingBottom) {
-// return;
-// }
-
- contentPaddingLeft = left;
- contentPaddingTop = top;
- contentPaddingRight = right;
- contentPaddingBottom = bottom;
-
- int[] userLocationViewPadding = mapboxMap.getMyLocationViewSettings().getPadding();
- left += userLocationViewPadding[0];
- top += userLocationViewPadding[1];
- right += userLocationViewPadding[2];
- bottom += userLocationViewPadding[3];
-
- nativeMapView.setContentPadding(top / screenDensity, left / screenDensity, bottom / screenDensity, right / screenDensity);
- }
-
- public void invalidateContentPadding() {
- setContentPadding(contentPaddingLeft, contentPaddingTop, contentPaddingRight, contentPaddingBottom);
-
- if (!mapboxMap.getTrackingSettings().isLocationTrackingDisabled()) {
- setFocalPoint(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY()));
- } else {
- setFocalPoint(null);
- }
- }
-
- double getMetersPerPixelAtLatitude(@FloatRange(from = -180, to = 180) double latitude) {
- if (destroyed) {
- return 0;
- }
-
- return nativeMapView.getMetersPerPixelAtLatitude(latitude, getZoom()) / screenDensity;
- }
-
- //
// Rendering
//
@@ -1095,16 +715,8 @@ public class MapView extends FrameLayout {
}
if (!isInEditMode()) {
- nativeMapView.resizeView((int) (width / screenDensity), (int) (height / screenDensity));
- }
- }
-
- double getScale() {
- if (destroyed) {
- return 0;
+ nativeMapView.resizeView(width, height);
}
-
- return nativeMapView.getScale();
}
private class SurfaceCallback implements SurfaceHolder.Callback {
@@ -1181,7 +793,8 @@ public class MapView extends FrameLayout {
if (destroyed) {
return;
}
- compassView.update(getDirection());
+ // TODO move to transform. java
+ compassView.update(mapboxMap.getTransform().getBearing());
myLocationView.update();
mapboxMap.getMarkerViewManager().update();
@@ -1191,52 +804,6 @@ public class MapView extends FrameLayout {
}
}
- void updateCameraPosition(@NonNull CameraPosition position) {
- myLocationView.setCameraPosition(position);
- mapboxMap.getMarkerViewManager().setTilt((float) position.tilt);
- }
-
- double getBearing() {
- if (destroyed) {
- return 0;
- }
-
- double direction = -nativeMapView.getBearing();
-
- while (direction > 360) {
- direction -= 360;
- }
- while (direction < 0) {
- direction += 360;
- }
-
- return direction;
- }
-
- void setBearing(double bearing) {
- if (destroyed) {
- return;
- }
- myLocationView.setBearing(bearing);
- nativeMapView.setBearing(bearing);
- }
-
- void setBearing(double bearing, long duration) {
- if (destroyed) {
- return;
- }
- myLocationView.setBearing(bearing);
- nativeMapView.setBearing(bearing, duration);
- }
-
- void setBearing(double bearing, float focalX, float focalY) {
- if (destroyed) {
- return;
- }
- myLocationView.setBearing(bearing);
- nativeMapView.setBearing(bearing, focalX, focalY);
- }
-
//
// View events
//
@@ -1267,898 +834,8 @@ public class MapView extends FrameLayout {
return;
}
- // Required by ZoomButtonController (from Android SDK documentation)
- if (visibility == View.VISIBLE) {
- if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(true);
- }
- } else {
- if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(false);
- }
- }
- }
-
- //
- // Touch events
- //
-
- /**
- * Helper method for tracking gesture events
- *
- * @param gestureId Type of Gesture See {@see MapboxEvent#GESTURE_SINGLETAP MapboxEvent#GESTURE_DOUBLETAP MapboxEvent#GESTURE_TWO_FINGER_SINGLETAP MapboxEvent#GESTURE_QUICK_ZOOM MapboxEvent#GESTURE_PAN_START MapboxEvent#GESTURE_PINCH_START MapboxEvent#GESTURE_ROTATION_START MapboxEvent#GESTURE_PITCH_START}
- * @param xCoordinate Original x screen coordinate at start of gesture
- * @param yCoordinate Original y screen cooridnate at start of gesture
- */
- private void trackGestureEvent(@NonNull String gestureId, float xCoordinate, float yCoordinate) {
- LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
-
- // NaN and Infinite checks to prevent JSON errors at send to server time
- if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) {
- Timber.d("trackGestureEvent() has a NaN lat or lon. Returning.");
- return;
- }
-
- if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) {
- Timber.d("trackGestureEvent() has an Infinite lat or lon. Returning.");
- return;
- }
-
- Hashtable<String, Object> evt = new Hashtable<>();
- evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_CLICK);
- evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
- evt.put(MapboxEvent.KEY_GESTURE_ID, gestureId);
- evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude());
- evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude());
- evt.put(MapboxEvent.KEY_ZOOM, mapboxMap.getCameraPosition().zoom);
-
- MapboxEventManager.getMapboxEventManager().pushEvent(evt);
- }
-
- /**
- * Helper method for tracking DragEnd gesture event
- * See {@see MapboxEvent#TYPE_MAP_DRAGEND}
- *
- * @param xCoordinate Original x screen coordinate at end of drag
- * @param yCoordinate Orginal y screen coordinate at end of drag
- */
- private void trackGestureDragEndEvent(float xCoordinate, float yCoordinate) {
- LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
-
- // NaN and Infinite checks to prevent JSON errors at send to server time
- if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) {
- Timber.d("trackGestureDragEndEvent() has a NaN lat or lon. Returning.");
- return;
- }
-
- if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) {
- Timber.d("trackGestureDragEndEvent() has an Infinite lat or lon. Returning.");
- return;
- }
-
- Hashtable<String, Object> evt = new Hashtable<>();
- evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_DRAGEND);
- evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
- evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude());
- evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude());
- evt.put(MapboxEvent.KEY_ZOOM, mapboxMap.getCameraPosition().zoom);
-
- MapboxEventManager.getMapboxEventManager().pushEvent(evt);
- }
-
- // Called when user touches the screen, all positions are absolute
- @Override
- public boolean onTouchEvent(@NonNull MotionEvent event) {
- // Check and ignore non touch or left clicks
- if (destroyed) {
- return super.onTouchEvent(event);
- }
-
- if ((event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) {
- return false;
- }
-
- // Check two finger gestures first
- rotateGestureDetector.onTouchEvent(event);
- scaleGestureDetector.onTouchEvent(event);
- shoveGestureDetector.onTouchEvent(event);
-
- // Handle two finger tap
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- // First pointer down
- nativeMapView.setGestureInProgress(true);
- break;
-
- case MotionEvent.ACTION_POINTER_DOWN:
- // Second pointer down
- twoTap = event.getPointerCount() == 2
- && mapboxMap.getUiSettings().isZoomGesturesEnabled();
- if (twoTap) {
- // Confirmed 2nd Finger Down
- trackGestureEvent(MapboxEvent.GESTURE_TWO_FINGER_SINGLETAP, event.getX(), event.getY());
- }
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- // Second pointer up
- break;
-
- case MotionEvent.ACTION_UP:
- // First pointer up
- long tapInterval = event.getEventTime() - event.getDownTime();
- boolean isTap = tapInterval <= ViewConfiguration.getTapTimeout();
- boolean inProgress = rotateGestureDetector.isInProgress()
- || scaleGestureDetector.isInProgress()
- || shoveGestureDetector.isInProgress();
-
- if (twoTap && isTap && !inProgress) {
- if (focalPoint != null) {
- zoom(false, focalPoint.x, focalPoint.y);
- } else {
- PointF focalPoint = TwoFingerGestureDetector.determineFocalPoint(event);
- zoom(false, focalPoint.x, focalPoint.y);
- }
- twoTap = false;
- return true;
- }
-
- // Scroll / Pan Has Stopped
- if (scrollInProgress) {
- trackGestureDragEndEvent(event.getX(), event.getY());
- scrollInProgress = false;
- }
-
- twoTap = false;
- nativeMapView.setGestureInProgress(false);
- break;
-
- case MotionEvent.ACTION_CANCEL:
- twoTap = false;
- nativeMapView.setGestureInProgress(false);
- break;
- }
-
- boolean retVal = gestureDetector.onTouchEvent(event);
- return retVal || super.onTouchEvent(event);
- }
-
- // This class handles one finger gestures
- private class GestureListener extends GestureDetector.SimpleOnGestureListener {
-
- // Must always return true otherwise all events are ignored
- @Override
- @SuppressLint("ResourceType")
- public boolean onDown(MotionEvent event) {
- // Show the zoom controls
- if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(true);
- }
- return true;
- }
-
- // Called for double taps
- @Override
- public boolean onDoubleTapEvent(MotionEvent e) {
- if (destroyed || !mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- switch (e.getAction()) {
- case MotionEvent.ACTION_DOWN:
- break;
- case MotionEvent.ACTION_MOVE:
- break;
- case MotionEvent.ACTION_UP:
- if (quickZoom) {
- // insert here?
- quickZoom = false;
- break;
- }
-
- // Single finger double tap
- if (focalPoint != null) {
- // User provided focal point
- zoom(true, focalPoint.x, focalPoint.y);
- } else {
- // Zoom in on gesture
- zoom(true, e.getX(), e.getY());
- }
- break;
- }
-
- trackGestureEvent(MapboxEvent.GESTURE_DOUBLETAP, e.getX(), e.getY());
-
- return true;
- }
-
- @Override
- public boolean onSingleTapUp(MotionEvent motionEvent) {
- if (destroyed) {
- return false;
- }
- // Cancel any animation
- mapboxMap.cancelTransitions();
- return true;
- }
-
- @Override
- public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
- List<Marker> selectedMarkers = mapboxMap.getSelectedMarkers();
-
- PointF tapPoint = new PointF(motionEvent.getX(), motionEvent.getY());
- float toleranceSides = 4 * screenDensity;
- float toleranceTopBottom = 10 * screenDensity;
-
- RectF tapRect = new RectF(tapPoint.x - iconManager.getAverageIconWidth() / 2 - toleranceSides,
- tapPoint.y - iconManager.getAverageIconHeight() / 2 - toleranceTopBottom,
- tapPoint.x + iconManager.getAverageIconWidth() / 2 + toleranceSides,
- tapPoint.y + iconManager.getAverageIconHeight() / 2 + toleranceTopBottom);
-
- List<Marker> nearbyMarkers = annotationManager.getMarkersInRect(tapRect);
- long newSelectedMarkerId = -1;
-
- if (nearbyMarkers != null && nearbyMarkers.size() > 0) {
- Collections.sort(nearbyMarkers);
- for (Marker nearbyMarker : nearbyMarkers) {
- boolean found = false;
- for (Marker selectedMarker : selectedMarkers) {
- if (selectedMarker.equals(nearbyMarker)) {
- found = true;
- }
- }
- if (!found) {
- newSelectedMarkerId = nearbyMarker.getId();
- break;
- }
- }
- }
-
- if (newSelectedMarkerId >= 0) {
- List<Annotation> annotations = mapboxMap.getAnnotations();
- int count = annotations.size();
- for (int i = 0; i < count; i++) {
- Annotation annotation = annotations.get(i);
- if (annotation instanceof Marker) {
- if (annotation.getId() == newSelectedMarkerId) {
- if (selectedMarkers.isEmpty() || !selectedMarkers.contains(annotation)) {
- if (!(annotation instanceof MarkerView)) {
- mapboxMap.selectMarker((Marker) annotation);
- } else {
- mapboxMap.getMarkerViewManager().onClickMarkerView((MarkerView) annotation);
- }
- }
- break;
- }
- }
- }
- } else {
- if (mapboxMap.getUiSettings().isDeselectMarkersOnTap()) {
- // deselect any selected marker
- mapboxMap.deselectMarkers();
- }
-
- // notify app of map click
- MapboxMap.OnMapClickListener listener = mapboxMap.getOnMapClickListener();
- if (listener != null) {
- LatLng point = projection.fromScreenLocation(tapPoint);
- listener.onMapClick(point);
- }
- }
-
- trackGestureEvent(MapboxEvent.GESTURE_SINGLETAP, motionEvent.getX(), motionEvent.getY());
- return true;
- }
-
- // Called for a long press
- @Override
- public void onLongPress(MotionEvent motionEvent) {
- MapboxMap.OnMapLongClickListener listener = mapboxMap.getOnMapLongClickListener();
- if (listener != null && !quickZoom) {
- LatLng point = projection.fromScreenLocation(new PointF(motionEvent.getX(), motionEvent.getY()));
- listener.onMapLongClick(point);
- }
- }
-
- // Called for flings
- @Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- if (destroyed || !mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(true, false);
-
- double decelerationRate = 1;
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- double offsetX = velocityX * decelerationRate / 4 / screenDensity;
- double offsetY = velocityY * decelerationRate / 4 / screenDensity;
-
- nativeMapView.setGestureInProgress(true);
- nativeMapView.moveBy(offsetX, offsetY, (long) (decelerationRate * 1000.0f));
- nativeMapView.setGestureInProgress(false);
-
- MapboxMap.OnFlingListener listener = mapboxMap.getOnFlingListener();
- if (listener != null) {
- listener.onFling();
- }
-
- trackGestureEvent(MapboxEvent.GESTURE_PAN_START, e1.getX(), e1.getY());
- return true;
- }
-
- // Called for drags
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- if (!scrollInProgress) {
- scrollInProgress = true;
- }
- if (destroyed || !mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- if (dragStarted) {
- return false;
- }
-
- requestDisallowInterceptTouchEvent(true);
-
- // reset tracking if needed
- mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(true, false);
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // Scroll the map
- nativeMapView.moveBy(-distanceX / screenDensity, -distanceY / screenDensity);
-
- MapboxMap.OnScrollListener listener = mapboxMap.getOnScrollListener();
- if (listener != null) {
- listener.onScroll();
- }
- return true;
- }
- }
-
- // This class handles two finger gestures and double-tap drag gestures
- private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
-
- long beginTime = 0;
- float scaleFactor = 1.0f;
-
- // Called when two fingers first touch the screen
- @Override
- public boolean onScaleBegin(ScaleGestureDetector detector) {
- if (destroyed || !mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- beginTime = detector.getEventTime();
- trackGestureEvent(MapboxEvent.GESTURE_PINCH_START, detector.getFocusX(), detector.getFocusY());
- return true;
- }
-
- // Called when fingers leave screen
- @Override
- public void onScaleEnd(ScaleGestureDetector detector) {
- beginTime = 0;
- scaleFactor = 1.0f;
- zoomStarted = false;
- }
-
- // Called each time a finger moves
- // Called for pinch zooms and quickzooms/quickscales
- @Override
- public boolean onScale(ScaleGestureDetector detector) {
- UiSettings uiSettings = mapboxMap.getUiSettings();
- if (destroyed || !uiSettings.isZoomGesturesEnabled()) {
- return super.onScale(detector);
- }
-
- // If scale is large enough ignore a tap
- scaleFactor *= detector.getScaleFactor();
- if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) {
- zoomStarted = true;
- }
-
- // Ignore short touches in case it is a tap
- // Also ignore small scales
- long time = detector.getEventTime();
- long interval = time - beginTime;
- if (!zoomStarted && (interval <= ViewConfiguration.getTapTimeout())) {
- return false;
- }
-
- if (!zoomStarted) {
- return false;
- }
-
- if (dragStarted) {
- return false;
- }
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // Gesture is a quickzoom if there aren't two fingers
- quickZoom = !twoTap;
-
- // make an assumption here; if the zoom center is specified by the gesture, it's NOT going
- // to be in the center of the map. Therefore the zoom will translate the map center, so tracking
- // should be disabled.
-
- mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(!quickZoom, false);
- // Scale the map
- if (focalPoint != null) {
- // arround user provided focal point
- nativeMapView.scaleBy(detector.getScaleFactor(), focalPoint.x / screenDensity, focalPoint.y / screenDensity);
- } else if (quickZoom) {
- // around center map
- nativeMapView.scaleBy(detector.getScaleFactor(), (getWidth() / 2) / screenDensity, (getHeight() / 2) / screenDensity);
- } else {
- // around gesture
- nativeMapView.scaleBy(detector.getScaleFactor(), detector.getFocusX() / screenDensity, detector.getFocusY() / screenDensity);
- }
-
- return true;
- }
- }
-
- // This class handles two finger rotate gestures
- private class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
-
- long beginTime = 0;
- float totalAngle = 0.0f;
- boolean started = false;
-
- // Called when two fingers first touch the screen
- @Override
- public boolean onRotateBegin(RotateGestureDetector detector) {
- if (destroyed || !mapboxMap.getTrackingSettings().isRotateGestureCurrentlyEnabled()) {
- return false;
- }
-
- beginTime = detector.getEventTime();
- trackGestureEvent(MapboxEvent.GESTURE_ROTATION_START, detector.getFocusX(), detector.getFocusY());
- return true;
- }
-
- // Called when the fingers leave the screen
- @Override
- public void onRotateEnd(RotateGestureDetector detector) {
- beginTime = 0;
- totalAngle = 0.0f;
- started = false;
- }
-
- // Called each time one of the two fingers moves
- // Called for rotation
- @Override
- public boolean onRotate(RotateGestureDetector detector) {
- if (destroyed || !mapboxMap.getTrackingSettings().isRotateGestureCurrentlyEnabled() || dragStarted) {
- return false;
- }
-
- // If rotate is large enough ignore a tap
- // Also is zoom already started, don't rotate
- totalAngle += detector.getRotationDegreesDelta();
- if (!zoomStarted && ((totalAngle > 20.0f) || (totalAngle < -20.0f))) {
- started = true;
- }
-
- // Ignore short touches in case it is a tap
- // Also ignore small rotate
- long time = detector.getEventTime();
- long interval = time - beginTime;
- if (!started && (interval <= ViewConfiguration.getTapTimeout())) {
- return false;
- }
-
- if (!started) {
- return false;
- }
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // rotation constitutes translation of anything except the center of
- // rotation, so cancel both location and bearing tracking if required
-
- mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(true, true);
-
- // Get rotate value
- double bearing = nativeMapView.getBearing();
- bearing += detector.getRotationDegreesDelta();
-
- // Rotate the map
- if (focalPoint != null) {
- // User provided focal point
- setBearing(bearing, focalPoint.x / screenDensity, focalPoint.y / screenDensity);
- } else {
- // around gesture
- setBearing(bearing, detector.getFocusX() / screenDensity, detector.getFocusY() / screenDensity);
- }
- return true;
- }
- }
-
- // This class handles a vertical two-finger shove. (If you place two fingers on screen with
- // less than a 20 degree angle between them, this will detect movement on the Y-axis.)
- private class ShoveGestureListener implements ShoveGestureDetector.OnShoveGestureListener {
-
- long beginTime = 0;
- float totalDelta = 0.0f;
- boolean started = false;
-
- @Override
- public boolean onShoveBegin(ShoveGestureDetector detector) {
- if (!mapboxMap.getUiSettings().isTiltGesturesEnabled()) {
- return false;
- }
-
- beginTime = detector.getEventTime();
- trackGestureEvent(MapboxEvent.GESTURE_PITCH_START, detector.getFocusX(), detector.getFocusY());
- return true;
- }
-
- @Override
- public void onShoveEnd(ShoveGestureDetector detector) {
- beginTime = 0;
- totalDelta = 0.0f;
- started = false;
- dragStarted = false;
- }
-
- @Override
- public boolean onShove(ShoveGestureDetector detector) {
- if (destroyed || !mapboxMap.getUiSettings().isTiltGesturesEnabled()) {
- return false;
- }
-
- // If tilt is large enough ignore a tap
- // Also if zoom already started, don't tilt
- totalDelta += detector.getShovePixelsDelta();
- if (!zoomStarted && ((totalDelta > 10.0f) || (totalDelta < -10.0f))) {
- started = true;
- }
-
- // Ignore short touches in case it is a tap
- // Also ignore small tilt
- long time = detector.getEventTime();
- long interval = time - beginTime;
- if (!started && (interval <= ViewConfiguration.getTapTimeout())) {
- return false;
- }
-
- if (!started) {
- return false;
- }
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // Get tilt value (scale and clamp)
- double pitch = getTilt();
- pitch -= 0.1 * detector.getShovePixelsDelta();
- pitch = Math.max(MapboxConstants.MINIMUM_TILT, Math.min(MapboxConstants.MAXIMUM_TILT, pitch));
-
- // Tilt the map
- mapboxMap.setTilt(pitch);
-
- dragStarted = true;
-
- return true;
- }
- }
-
- // This class handles input events from the zoom control buttons
- // Zoom controls allow single touch only devices to zoom in and out
- private class OnZoomListener implements ZoomButtonsController.OnZoomListener {
-
- // Not used
- @Override
- public void onVisibilityChanged(boolean visible) {
- // Ignore
- }
-
- // Called when user pushes a zoom button
- @Override
- public void onZoom(boolean zoomIn) {
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return;
- }
- zoom(zoomIn);
- }
- }
-
- //
- // Input events
- //
-
- // Called when the user presses a key, also called for repeating keys held
- // down
- @Override
- public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
- if (destroyed) {
- return super.onKeyDown(keyCode, event);
- }
-
- // If the user has held the scroll key down for a while then accelerate
- // the scroll speed
- double scrollDist = event.getRepeatCount() >= 5 ? 50.0 : 10.0;
-
- // Check which key was pressed via hardware/real key code
- switch (keyCode) {
- // Tell the system to track these keys for long presses on
- // onKeyLongPress is fired
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- event.startTracking();
- return true;
-
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // Move left
- nativeMapView.moveBy(scrollDist / screenDensity, 0.0 / screenDensity);
- return true;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // Move right
- nativeMapView.moveBy(-scrollDist / screenDensity, 0.0 / screenDensity);
- return true;
-
- case KeyEvent.KEYCODE_DPAD_UP:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // Move up
- nativeMapView.moveBy(0.0 / screenDensity, scrollDist / screenDensity);
- return true;
-
- case KeyEvent.KEYCODE_DPAD_DOWN:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // Move down
- nativeMapView.moveBy(0.0 / screenDensity, -scrollDist / screenDensity);
- return true;
-
- default:
- // We are not interested in this key
- return super.onKeyUp(keyCode, event);
- }
- }
-
- // Called when the user long presses a key that is being tracked
- @Override
- public boolean onKeyLongPress(int keyCode, KeyEvent event) {
- // Check which key was pressed via hardware/real key code
- switch (keyCode) {
- // Tell the system to track these keys for long presses on
- // onKeyLongPress is fired
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- // Zoom out
- zoom(false);
- return true;
-
- default:
- // We are not interested in this key
- return super.onKeyUp(keyCode, event);
- }
- }
-
- // Called when the user releases a key
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- // Check if the key action was canceled (used for virtual keyboards)
- if (event.isCanceled()) {
- return super.onKeyUp(keyCode, event);
- }
-
- // Check which key was pressed via hardware/real key code
- // Note if keyboard does not have physical key (ie primary non-shifted
- // key) then it will not appear here
- // Must use the key character map as physical to character is not
- // fixed/guaranteed
- switch (keyCode) {
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- // Zoom in
- zoom(true);
- return true;
- }
-
- // We are not interested in this key
- return super.onKeyUp(keyCode, event);
- }
-
- // Called for trackball events, all motions are relative in device specific
- // units
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- if (destroyed) {
- return false;
- }
- // Choose the action
- switch (event.getActionMasked()) {
- // The trackball was rotated
- case MotionEvent.ACTION_MOVE:
- if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) {
- return false;
- }
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // Scroll the map
- nativeMapView.moveBy(-10.0 * event.getX() / screenDensity, -10.0 * event.getY() / screenDensity);
- return true;
-
- // Trackball was pushed in so start tracking and tell system we are
- // interested
- // We will then get the up action
- case MotionEvent.ACTION_DOWN:
- // Set up a delayed callback to check if trackball is still
- // After waiting the system long press time out
- if (currentTrackballLongPressTimeOut != null) {
- currentTrackballLongPressTimeOut.cancel();
- currentTrackballLongPressTimeOut = null;
- }
- currentTrackballLongPressTimeOut = new TrackballLongPressTimeOut();
- postDelayed(currentTrackballLongPressTimeOut,
- ViewConfiguration.getLongPressTimeout());
- return true;
-
- // Trackball was released
- case MotionEvent.ACTION_UP:
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- // Only handle if we have not already long pressed
- if (currentTrackballLongPressTimeOut != null) {
- // Zoom in
- zoom(true);
- }
- return true;
-
- // Trackball was cancelled
- case MotionEvent.ACTION_CANCEL:
- if (currentTrackballLongPressTimeOut != null) {
- currentTrackballLongPressTimeOut.cancel();
- currentTrackballLongPressTimeOut = null;
- }
- return true;
-
- default:
- // We are not interested in this event
- return super.onTrackballEvent(event);
- }
- }
-
- // This class implements the trackball long press time out callback
- private class TrackballLongPressTimeOut implements Runnable {
-
- // Track if we have been cancelled
- private boolean cancelled;
-
- TrackballLongPressTimeOut() {
- cancelled = false;
- }
-
- // Cancel the timeout
- public void cancel() {
- cancelled = true;
- }
-
- // Called when long press time out expires
- @Override
- public void run() {
- // Check if the trackball is still pressed
- if (!cancelled) {
- // Zoom out
- zoom(false);
-
- // Ensure the up action is not run
- currentTrackballLongPressTimeOut = null;
- }
- }
- }
-
- // Called for events that don't fit the other handlers
- // such as mouse scroll events, mouse moves, joystick, trackpad
- @Override
- public boolean onGenericMotionEvent(MotionEvent event) {
- if (destroyed) {
- return false;
- }
- // Mouse events
- //if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { // this is not available before API 18
- if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) {
- // Choose the action
- switch (event.getActionMasked()) {
- // Mouse scrolls
- case MotionEvent.ACTION_SCROLL:
- if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) {
- return false;
- }
-
- // Cancel any animation
- mapboxMap.cancelTransitions();
-
- // Get the vertical scroll amount, one click = 1
- float scrollDist = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
-
- // Scale the map by the appropriate power of two factor
- nativeMapView.scaleBy(Math.pow(2.0, scrollDist), event.getX() / screenDensity, event.getY() / screenDensity);
-
- return true;
-
- default:
- // We are not interested in this event
- return super.onGenericMotionEvent(event);
- }
- }
-
- // We are not interested in this event
- return super.onGenericMotionEvent(event);
- }
-
- // Called when the mouse pointer enters or exits the view
- // or when it fades in or out due to movement
- @Override
- public boolean onHoverEvent(@NonNull MotionEvent event) {
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_HOVER_ENTER:
- case MotionEvent.ACTION_HOVER_MOVE:
- // Show the zoom controls
- if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(true);
- }
- return true;
-
- case MotionEvent.ACTION_HOVER_EXIT:
- // Hide the zoom controls
- if (mapboxMap.getUiSettings().isZoomControlsEnabled()) {
- zoomButtonsController.setVisible(false);
- }
- return true;
-
- default:
- // We are not interested in this event
- return super.onHoverEvent(event);
+ if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) {
+ zoomButtonsController.setVisible(visibility == View.VISIBLE);
}
}
@@ -2230,133 +907,6 @@ public class MapView extends FrameLayout {
nativeMapView.onMapChangedEventDispatch(mapChange);
}
- //
- // User location
- //
-
- void setMyLocationEnabled(boolean enabled) {
- myLocationView.setEnabled(enabled);
- }
-
- Location getMyLocation() {
- return myLocationView.getLocation();
- }
-
- void setOnMyLocationChangeListener(@Nullable final MapboxMap.OnMyLocationChangeListener listener) {
- if (listener != null) {
- myLocationListener = new LocationListener() {
- @Override
- public void onLocationChanged(Location location) {
- if (listener != null) {
- listener.onMyLocationChange(location);
- }
- }
- };
- LocationServices.getLocationServices(getContext()).addLocationListener(myLocationListener);
- } else {
- LocationServices.getLocationServices(getContext()).removeLocationListener(myLocationListener);
- myLocationListener = null;
- }
- }
-
- void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
- if (myLocationTrackingMode != MyLocationTracking.TRACKING_NONE && !mapboxMap.isMyLocationEnabled()) {
- mapboxMap.setMyLocationEnabled(true);
- }
- myLocationView.setMyLocationTrackingMode(myLocationTrackingMode);
-
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
- setFocalPoint(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY()));
- } else {
- setFocalPoint(null);
- }
-
- MapboxMap.OnMyLocationTrackingModeChangeListener listener = mapboxMap.getOnMyLocationTrackingModeChangeListener();
- if (listener != null) {
- listener.onMyLocationTrackingModeChange(myLocationTrackingMode);
- }
- }
-
- void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
- if (myBearingTrackingMode != MyBearingTracking.NONE && !mapboxMap.isMyLocationEnabled()) {
- mapboxMap.setMyLocationEnabled(true);
- }
- myLocationView.setMyBearingTrackingMode(myBearingTrackingMode);
- MapboxMap.OnMyBearingTrackingModeChangeListener listener = mapboxMap.getOnMyBearingTrackingModeChangeListener();
- if (listener != null) {
- listener.onMyBearingTrackingModeChange(myBearingTrackingMode);
- }
- }
-
- boolean isPermissionsAccepted() {
- return (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) ||
- ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
- }
-
- //
- // Compass
- //
-
- void setCompassEnabled(boolean compassEnabled) {
- compassView.setEnabled(compassEnabled);
- }
-
- void setCompassGravity(int gravity) {
- setWidgetGravity(compassView, gravity);
- }
-
- void setCompassMargins(int left, int top, int right, int bottom) {
- setWidgetMargins(compassView, left, top, right, bottom);
- }
-
- void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) {
- compassView.fadeCompassViewFacingNorth(compassFadeFacingNorth);
- }
-
- //
- // Logo
- //
-
- void setLogoGravity(int gravity) {
- setWidgetGravity(logoView, gravity);
- }
-
- void setLogoMargins(int left, int top, int right, int bottom) {
- setWidgetMargins(logoView, left, top, right, bottom);
- }
-
- void setLogoEnabled(boolean visible) {
- logoView.setVisibility(visible ? View.VISIBLE : View.GONE);
- }
-
- //
- // Attribution
- //
-
- void setAttributionGravity(int gravity) {
- setWidgetGravity(attributionsView, gravity);
- }
-
- void setAttributionMargins(int left, int top, int right, int bottom) {
- setWidgetMargins(attributionsView, left, top, right, bottom);
- }
-
- void setAttributionEnabled(int visibility) {
- attributionsView.setVisibility(visibility);
- }
-
- void setAtttibutionTintColor(int tintColor) {
- // Check that the tint color being passed in isn't transparent.
- if (Color.alpha(tintColor) == 0) {
- ColorUtils.setTintList(attributionsView, ContextCompat.getColor(getContext(), R.color.mapbox_blue));
- } else {
- ColorUtils.setTintList(attributionsView, tintColor);
- }
- }
-
- int getAttributionTintColor() {
- return mapboxMap.getUiSettings().getAttributionTintColor();
- }
/**
* Sets a callback object which will be triggered when the {@link MapboxMap} instance is ready to be used.
@@ -2382,14 +932,6 @@ public class MapView extends FrameLayout {
this.mapboxMap = mapboxMap;
}
- MyLocationView getUserLocationView() {
- return myLocationView;
- }
-
- NativeMapView getNativeMapView() {
- return nativeMapView;
- }
-
//
// Snapshot API
//
@@ -2437,26 +979,6 @@ public class MapView extends FrameLayout {
}
}
- //
- // View utility methods
- //
-
- private void setWidgetGravity(@NonNull final View view, int gravity) {
- LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
- layoutParams.gravity = gravity;
- view.setLayoutParams(layoutParams);
- }
-
- private void setWidgetMargins(@NonNull final View view, int left, int top, int right, int bottom) {
- LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
- left += contentPaddingLeft;
- top += contentPaddingTop;
- right += contentPaddingRight;
- bottom += contentPaddingBottom;
- layoutParams.setMargins(left, top, right, bottom);
- view.setLayoutParams(layoutParams);
- }
-
private static class AttributionOnClickListener implements View.OnClickListener, DialogInterface.OnClickListener {
private static final int ATTRIBUTION_INDEX_IMPROVE_THIS_MAP = 2;
@@ -2511,16 +1033,16 @@ public class MapView extends FrameLayout {
}
});
- AlertDialog telemDialog = builder.show();
- telemDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(mapView.getAttributionTintColor());
- telemDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(mapView.getAttributionTintColor());
- telemDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setTextColor(mapView.getAttributionTintColor());
+ builder.show();
return;
}
String url = context.getResources().getStringArray(R.array.mapbox_attribution_links)[which];
if (which == ATTRIBUTION_INDEX_IMPROVE_THIS_MAP) {
- LatLng latLng = mapView.getMapboxMap().getCameraPosition().target;
- url = String.format(url, latLng.getLongitude(), latLng.getLatitude(), (int) mapView.getZoom());
+ CameraPosition cameraPosition = mapView.getMapboxMap().getCameraPosition();
+ if (cameraPosition != null) {
+ url = String.format(url, cameraPosition.target.getLongitude(),
+ cameraPosition.target.getLatitude(), (int) cameraPosition.zoom);
+ }
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
@@ -2767,4 +1289,66 @@ public class MapView extends FrameLayout {
void onMapChanged(@MapChange int change);
}
+ // This class handles input events from the zoom control buttons
+ // Zoom controls allow single touch only devices to zoom in and out
+ private class OnZoomListener implements ZoomButtonsController.OnZoomListener {
+
+ private UiSettings uiSettings;
+ private Transform transform;
+
+ OnZoomListener(MapboxMap mapboxMap) {
+ this.uiSettings = mapboxMap.getUiSettings();
+ this.transform = mapboxMap.getTransform();
+ }
+
+ // Not used
+ @Override
+ public void onVisibilityChanged(boolean visible) {
+ // Ignore
+ }
+
+ // Called when user pushes a zoom button
+ @Override
+ public void onZoom(boolean zoomIn) {
+ if (!uiSettings.isZoomGesturesEnabled()) {
+ return;
+ }
+ transform.zoom(zoomIn);
+ }
+ }
+
+ private class FocalPointInvalidator implements FocalPointChangeListener {
+
+ @Override
+ public void onFocalPointChanged(PointF pointF) {
+ mapGestureDetector.setFocalPoint(pointF);
+ }
+ }
+
+ private class RegisterTouchListener implements MapboxMap.OnRegisterTouchListener {
+
+ @Override
+ public void onRegisterMapClickListener(MapboxMap.OnMapClickListener listener) {
+ mapGestureDetector.setOnMapClickListener(listener);
+ }
+
+ @Override
+ public void onRegisterMapLongClickListener(MapboxMap.OnMapLongClickListener listener) {
+ mapGestureDetector.setOnMapLongClickListener(listener);
+ }
+
+ @Override
+ public void onRegisterScrollListener(MapboxMap.OnScrollListener listener) {
+ mapGestureDetector.setOnScrollListener(listener);
+ }
+
+ @Override
+ public void onRegisterFlingListener(MapboxMap.OnFlingListener listener) {
+ mapGestureDetector.setOnFlingListener(listener);
+ }
+ }
+
+ NativeMapView getNativeMapView() {
+ return nativeMapView;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
index fa856a7aa7..2923fa2e52 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
@@ -1,20 +1,27 @@
package com.mapbox.mapboxsdk.maps;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.RectF;
import android.location.Location;
+import android.os.Handler;
import android.support.annotation.FloatRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.v4.util.Pools;
+
import timber.log.Timber;
+
+import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ZoomButtonsController;
import com.mapbox.mapboxsdk.MapboxAccountManager;
+import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
@@ -40,6 +47,7 @@ import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.NoSuchLayerException;
import com.mapbox.mapboxsdk.style.sources.NoSuchSourceException;
import com.mapbox.mapboxsdk.style.sources.Source;
+import com.mapbox.mapboxsdk.utils.ColorUtils;
import com.mapbox.services.commons.geojson.Feature;
import java.lang.reflect.ParameterizedType;
@@ -54,46 +62,134 @@ import java.util.List;
* Note: Similar to a View object, a MapboxMap should only be read and modified from the main thread.
* </p>
*/
-public class MapboxMap {
-
- private MapView mapView;
- private UiSettings uiSettings;
- private TrackingSettings trackingSettings;
- private MyLocationViewSettings myLocationViewSettings;
- private Projection projection;
- private Transform transform;
- private boolean myLocationEnabled;
+public final class MapboxMap {
- private MapboxMap.OnMapClickListener onMapClickListener;
- private MapboxMap.OnMapLongClickListener onMapLongClickListener;
+ private final NativeMapView nativeMapView;
+ private final UiSettings uiSettings;
+ private final TrackingSettings trackingSettings;
+ private final Projection projection;
+ private final Transform transform;
+ private final AnnotationManager annotationManager;
+ private final MyLocationViewSettings myLocationViewSettings;
+ private final OnRegisterTouchListener onRegisterTouchListener;
-
- private MapboxMap.OnFlingListener onFlingListener;
- private MapboxMap.OnScrollListener onScrollListener;
- private MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener;
- private MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener;
private MapboxMap.OnFpsChangedListener onFpsChangedListener;
- private AnnotationManager annotationManager;
- private InfoWindowManager infoWindowManager;
+ private boolean myLocationEnabled;
private double maxZoomLevel = -1;
private double minZoomLevel = -1;
- MapboxMap(@NonNull MapView mapView, IconManager iconManager) {
- this.mapView = mapView;
- uiSettings = new UiSettings(mapView);
- trackingSettings = new TrackingSettings(this.mapView, uiSettings);
- projection = new Projection(mapView);
- infoWindowManager = new InfoWindowManager();
- annotationManager = new AnnotationManager(mapView.getNativeMapView(), iconManager, infoWindowManager);
-
- // TODO inject NativeMapView https://github.com/mapbox/mapbox-gl-native/issues/4100
- NativeMapView nativeMapView = mapView.getNativeMapView();
- if (nativeMapView != null) {
- transform = new Transform(nativeMapView, this);
- nativeMapView.addOnMapChangedListener(new CameraInvalidator());
+ MapboxMap(NativeMapView map, Transform transform, UiSettings ui, TrackingSettings tracking, MyLocationViewSettings myLocationView,
+ Projection projection, OnRegisterTouchListener listener, AnnotationManager annotations) {
+ this.nativeMapView = map;
+ this.uiSettings = ui;
+ this.trackingSettings = tracking;
+ this.projection = projection;
+ this.myLocationViewSettings = myLocationView;
+ this.annotationManager = annotations.bind(this);
+ this.transform = transform;
+ this.onRegisterTouchListener = listener;
+ }
+
+ void initialise(Context context, MapboxMapOptions options) {
+ // TODO migrate code from this method to the classes they impact themselves
+ setDebugActive(options.getDebugActive());
+
+ CameraPosition position = options.getCamera();
+ if (position != null && !position.equals(CameraPosition.DEFAULT)) {
+ transform.moveCamera(this, CameraUpdateFactory.newCameraPosition(position), null);
+ myLocationViewSettings.setTilt(position.tilt);
+ }
+
+ // api base url
+ String apiBaseUrl = options.getApiBaseUrl();
+ if (!TextUtils.isEmpty(apiBaseUrl)) {
+ nativeMapView.setApiBaseUrl(apiBaseUrl);
+ }
+
+ // access token
+ String accessToken = options.getAccessToken();
+ if (!TextUtils.isEmpty(accessToken)) {
+ nativeMapView.setAccessToken(accessToken);
+ }else{
+ nativeMapView.setAccessToken(MapboxAccountManager.getInstance().getAccessToken());
+ }
+
+ // style url
+ String style = options.getStyle();
+ if (!TextUtils.isEmpty(style)) {
+ nativeMapView.setStyleUrl(style);
+ }
+
+ // MyLocationView
+ myLocationViewSettings.setForegroundDrawable(
+ options.getMyLocationForegroundDrawable(), options.getMyLocationForegroundBearingDrawable());
+ myLocationViewSettings.setForegroundTintColor(options.getMyLocationForegroundTintColor());
+ myLocationViewSettings.setBackgroundDrawable(
+ options.getMyLocationBackgroundDrawable(), options.getMyLocationBackgroundPadding());
+ myLocationViewSettings.setBackgroundTintColor(options.getMyLocationBackgroundTintColor());
+ myLocationViewSettings.setAccuracyAlpha(options.getMyLocationAccuracyAlpha());
+ myLocationViewSettings.setAccuracyTintColor(options.getMyLocationAccuracyTintColor());
+ setMyLocationEnabled(options.getLocationEnabled());
+
+ // Enable gestures
+ uiSettings.setZoomGesturesEnabled(options.getZoomGesturesEnabled());
+ uiSettings.setZoomGestureChangeAllowed(options.getZoomGesturesEnabled());
+ uiSettings.setScrollGesturesEnabled(options.getScrollGesturesEnabled());
+ uiSettings.setScrollGestureChangeAllowed(options.getScrollGesturesEnabled());
+ uiSettings.setRotateGesturesEnabled(options.getRotateGesturesEnabled());
+ uiSettings.setRotateGestureChangeAllowed(options.getRotateGesturesEnabled());
+ uiSettings.setTiltGesturesEnabled(options.getTiltGesturesEnabled());
+ uiSettings.setTiltGestureChangeAllowed(options.getTiltGesturesEnabled());
+
+ // Ui Controls
+ uiSettings.setZoomControlsEnabled(options.getZoomControlsEnabled());
+
+ // Zoom
+ setMaxZoom(options.getMaxZoom());
+ setMinZoom(options.getMinZoom());
+
+ Resources resources = context.getResources();
+
+ // Compass
+ uiSettings.setCompassEnabled(options.getCompassEnabled());
+ uiSettings.setCompassGravity(options.getCompassGravity());
+ int[] compassMargins = options.getCompassMargins();
+ if (compassMargins != null) {
+ uiSettings.setCompassMargins(compassMargins[0], compassMargins[1], compassMargins[2], compassMargins[3]);
+ } else {
+ int tenDp = (int) resources.getDimension(R.dimen.mapbox_ten_dp);
+ uiSettings.setCompassMargins(tenDp, tenDp, tenDp, tenDp);
}
+ uiSettings.setCompassFadeFacingNorth(options.getCompassFadeFacingNorth());
+
+ // Logo
+ uiSettings.setLogoEnabled(options.getLogoEnabled());
+ uiSettings.setLogoGravity(options.getLogoGravity());
+ int[] logoMargins = options.getLogoMargins();
+ if (logoMargins != null) {
+ uiSettings.setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]);
+ } else {
+ int sixteenDp = (int) resources.getDimension(R.dimen.mapbox_sixteen_dp);
+ uiSettings.setLogoMargins(sixteenDp, sixteenDp, sixteenDp, sixteenDp);
+ }
+
+ // Attribution
+ uiSettings.setAttributionEnabled(options.getAttributionEnabled());
+ uiSettings.setAttributionGravity(options.getAttributionGravity());
+ int[] attributionMargins = options.getAttributionMargins();
+ if (attributionMargins != null) {
+ uiSettings.setAttributionMargins(attributionMargins[0], attributionMargins[1], attributionMargins[2], attributionMargins[3]);
+ } else {
+ int sevenDp = (int) resources.getDimension(R.dimen.mapbox_seven_dp);
+ int seventySixDp = (int) resources.getDimension(R.dimen.mapbox_seventy_six_dp);
+ uiSettings.setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp);
+ }
+
+ int attributionTintColor = options.getAttributionTintColor();
+ uiSettings.setAttributionTintColor(attributionTintColor != -1
+ ? attributionTintColor : ColorUtils.getPrimaryColor(context));
}
// Style
@@ -101,7 +197,7 @@ public class MapboxMap {
@Nullable
@UiThread
public Layer getLayer(@NonNull String layerId) {
- return getMapView().getNativeMapView().getLayer(layerId);
+ return nativeMapView.getLayer(layerId);
}
/**
@@ -116,7 +212,7 @@ public class MapboxMap {
public <T extends Layer> T getLayerAs(@NonNull String layerId) {
try {
//noinspection unchecked
- return (T) getMapView().getNativeMapView().getLayer(layerId);
+ return (T) nativeMapView.getLayer(layerId);
} catch (ClassCastException e) {
Timber.e(String.format("Layer: %s is a different type: %s", layerId, e.getMessage()));
return null;
@@ -141,7 +237,7 @@ public class MapboxMap {
*/
@UiThread
public void addLayer(@NonNull Layer layer, String before) {
- getMapView().getNativeMapView().addLayer(layer, before);
+ nativeMapView.addLayer(layer, before);
}
/**
@@ -152,7 +248,7 @@ public class MapboxMap {
*/
@UiThread
public void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
- getMapView().getNativeMapView().removeLayer(layerId);
+ nativeMapView.removeLayer(layerId);
}
/**
@@ -163,13 +259,13 @@ public class MapboxMap {
*/
@UiThread
public void removeLayer(@NonNull Layer layer) throws NoSuchLayerException {
- getMapView().getNativeMapView().removeLayer(layer);
+ nativeMapView.removeLayer(layer);
}
@Nullable
@UiThread
public Source getSource(@NonNull String sourceId) {
- return getMapView().getNativeMapView().getSource(sourceId);
+ return nativeMapView.getSource(sourceId);
}
/**
@@ -184,7 +280,7 @@ public class MapboxMap {
public <T extends Source> T getSourceAs(@NonNull String sourceId) {
try {
//noinspection unchecked
- return (T) getMapView().getNativeMapView().getSource(sourceId);
+ return (T) nativeMapView.getSource(sourceId);
} catch (ClassCastException e) {
Timber.e(String.format("Source: %s is a different type: %s", sourceId, e.getMessage()));
return null;
@@ -198,7 +294,7 @@ public class MapboxMap {
*/
@UiThread
public void addSource(@NonNull Source source) {
- getMapView().getNativeMapView().addSource(source);
+ nativeMapView.addSource(source);
}
/**
@@ -209,7 +305,7 @@ public class MapboxMap {
*/
@UiThread
public void removeSource(@NonNull String sourceId) throws NoSuchSourceException {
- getMapView().getNativeMapView().removeSource(sourceId);
+ nativeMapView.removeSource(sourceId);
}
/**
@@ -220,7 +316,7 @@ public class MapboxMap {
*/
@UiThread
public void removeSource(@NonNull Source source) throws NoSuchSourceException {
- getMapView().getNativeMapView().removeSource(source);
+ nativeMapView.removeSource(source);
}
/**
@@ -231,7 +327,7 @@ public class MapboxMap {
*/
@UiThread
public void addImage(@NonNull String name, @NonNull Bitmap image) {
- getMapView().getNativeMapView().addImage(name, image);
+ nativeMapView.addImage(name, image);
}
/**
@@ -241,7 +337,7 @@ public class MapboxMap {
*/
@UiThread
public void removeImage(String name) {
- getMapView().getNativeMapView().removeImage(name);
+ nativeMapView.removeImage(name);
}
//
@@ -263,7 +359,7 @@ public class MapboxMap {
return;
}
minZoomLevel = minZoom;
- mapView.setMinZoom(minZoom);
+ nativeMapView.setMinZoom(minZoom);
}
/**
@@ -276,7 +372,7 @@ public class MapboxMap {
@UiThread
public double getMinZoom() {
if (minZoomLevel == -1) {
- return minZoomLevel = mapView.getMinZoom();
+ return minZoomLevel = nativeMapView.getMinZoom();
}
return minZoomLevel;
}
@@ -300,7 +396,7 @@ public class MapboxMap {
return;
}
maxZoomLevel = maxZoom;
- mapView.setMaxZoom(maxZoom);
+ nativeMapView.setMaxZoom(maxZoom);
}
/**
@@ -313,7 +409,7 @@ public class MapboxMap {
@UiThread
public double getMaxZoom() {
if (maxZoomLevel == -1) {
- return maxZoomLevel = mapView.getMaxZoom();
+ return maxZoomLevel = nativeMapView.getMaxZoom();
}
return maxZoomLevel;
}
@@ -354,9 +450,6 @@ public class MapboxMap {
* @return the MyLocationViewSettings associated with this map
*/
public MyLocationViewSettings getMyLocationViewSettings() {
- if (myLocationViewSettings == null) {
- myLocationViewSettings = new MyLocationViewSettings(mapView, mapView.getUserLocationView());
- }
return myLocationViewSettings;
}
@@ -420,6 +513,9 @@ public class MapboxMap {
@UiThread
public final void moveCamera(CameraUpdate update) {
moveCamera(update, null);
+ // MapChange.REGION_DID_CHANGE_ANIMATED is not called for `jumpTo`
+ // invalidate camera position to provide OnCameraChange event.
+ invalidateCameraPosition();
}
/**
@@ -432,10 +528,10 @@ public class MapboxMap {
*/
@UiThread
public final void moveCamera(final CameraUpdate update, final MapboxMap.CancelableCallback callback) {
- mapView.post(new Runnable() {
+ new Handler().post(new Runnable() {
@Override
public void run() {
- transform.moveCamera(update, callback);
+ transform.moveCamera(MapboxMap.this, update, callback);
}
});
}
@@ -559,10 +655,10 @@ public class MapboxMap {
*/
@UiThread
public final void easeCamera(final CameraUpdate update, final int durationMs, final boolean easingInterpolator, final boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) {
- mapView.post(new Runnable() {
+ new Handler().post(new Runnable() {
@Override
public void run() {
- transform.easeCamera(update, durationMs, easingInterpolator, resetTrackingMode, callback);
+ transform.easeCamera(MapboxMap.this, update, durationMs, easingInterpolator, resetTrackingMode, callback);
}
});
}
@@ -634,10 +730,10 @@ public class MapboxMap {
*/
@UiThread
public final void animateCamera(final CameraUpdate update, final int durationMs, final MapboxMap.CancelableCallback callback) {
- mapView.post(new Runnable() {
+ new Handler().post(new Runnable() {
@Override
public void run() {
- transform.animateCamera(update, durationMs, callback);
+ transform.animateCamera(MapboxMap.this, update, durationMs, callback);
}
});
}
@@ -648,7 +744,7 @@ public class MapboxMap {
void invalidateCameraPosition() {
CameraPosition cameraPosition = transform.invalidateCameraPosition();
if (cameraPosition != null) {
- mapView.updateCameraPosition(cameraPosition);
+ transform.updateCameraPosition(cameraPosition);
}
}
@@ -674,7 +770,7 @@ public class MapboxMap {
*/
@UiThread
public boolean isDebugActive() {
- return mapView.isDebugActive();
+ return nativeMapView.getDebug();
}
/**
@@ -687,21 +783,21 @@ public class MapboxMap {
*/
@UiThread
public void setDebugActive(boolean debugActive) {
- mapView.setDebugActive(debugActive);
+ nativeMapView.setDebug(debugActive);
}
/**
* <p>
* Cycles through the map debug options.
* </p>
- * The value of {@link MapView#isDebugActive()} reflects whether there are
+ * The value of isDebugActive reflects whether there are
* any map debug options enabled or disabled.
*
- * @see MapView#isDebugActive()
+ * @see #isDebugActive()
*/
@UiThread
public void cycleDebugOptions() {
- mapView.cycleDebugOptions();
+ nativeMapView.cycleDebugOptions();
}
//
@@ -739,7 +835,7 @@ public class MapboxMap {
*/
@UiThread
public void setStyleUrl(@NonNull String url) {
- mapView.setStyleUrl(url);
+ nativeMapView.setStyleUrl(url);
}
/**
@@ -775,7 +871,7 @@ public class MapboxMap {
@UiThread
@NonNull
public String getStyleUrl() {
- return mapView.getStyleUrl();
+ return nativeMapView.getStyleUrl();
}
//
@@ -797,7 +893,7 @@ public class MapboxMap {
@Deprecated
@UiThread
public void setAccessToken(@NonNull String accessToken) {
- mapView.setAccessToken(accessToken);
+ nativeMapView.setAccessToken(accessToken);
}
/**
@@ -815,17 +911,13 @@ public class MapboxMap {
@UiThread
@Nullable
public String getAccessToken() {
- return mapView.getAccessToken();
+ return nativeMapView.getAccessToken();
}
//
// Annotations
//
- void setTilt(double tilt) {
- mapView.setTilt(tilt);
- }
-
/**
* <p>
* Adds a marker to this map.
@@ -1152,7 +1244,7 @@ public class MapboxMap {
Timber.w("marker was null, so just returning");
return;
}
- annotationManager.selectMarker(marker, this);
+ annotationManager.selectMarker(marker);
}
/**
@@ -1189,7 +1281,7 @@ public class MapboxMap {
* @return the associated MarkerViewManager
*/
public MarkerViewManager getMarkerViewManager() {
- return annotationManager.getMarkerViewManager(this);
+ return annotationManager.getMarkerViewManager();
}
//
@@ -1208,7 +1300,7 @@ public class MapboxMap {
*/
@UiThread
public void setInfoWindowAdapter(@Nullable InfoWindowAdapter infoWindowAdapter) {
- infoWindowManager.setInfoWindowAdapter(infoWindowAdapter);
+ annotationManager.getInfoWindowManager().setInfoWindowAdapter(infoWindowAdapter);
}
/**
@@ -1219,7 +1311,7 @@ public class MapboxMap {
@UiThread
@Nullable
public InfoWindowAdapter getInfoWindowAdapter() {
- return infoWindowManager.getInfoWindowAdapter();
+ return annotationManager.getInfoWindowManager().getInfoWindowAdapter();
}
/**
@@ -1229,7 +1321,7 @@ public class MapboxMap {
*/
@UiThread
public void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) {
- infoWindowManager.setAllowConcurrentMultipleOpenInfoWindows(allow);
+ annotationManager.getInfoWindowManager().setAllowConcurrentMultipleOpenInfoWindows(allow);
}
/**
@@ -1239,12 +1331,12 @@ public class MapboxMap {
*/
@UiThread
public boolean isAllowConcurrentMultipleOpenInfoWindows() {
- return infoWindowManager.isAllowConcurrentMultipleOpenInfoWindows();
+ return annotationManager.getInfoWindowManager().isAllowConcurrentMultipleOpenInfoWindows();
}
// Internal API
List<InfoWindow> getInfoWindows() {
- return infoWindowManager.getInfoWindows();
+ return annotationManager.getInfoWindowManager().getInfoWindows();
}
AnnotationManager getAnnotationManager() {
@@ -1279,7 +1371,7 @@ public class MapboxMap {
* @param bottom The bottom margin in pixels.
*/
public void setPadding(int left, int top, int right, int bottom) {
- mapView.setContentPadding(left, top, right, bottom);
+ projection.setContentPadding(new int[]{left, top, right, bottom}, myLocationViewSettings.getPadding());
uiSettings.invalidate();
}
@@ -1289,10 +1381,7 @@ public class MapboxMap {
* @return An array with length 4 in the LTRB order.
*/
public int[] getPadding() {
- return new int[]{mapView.getContentPaddingLeft(),
- mapView.getContentPaddingTop(),
- mapView.getContentPaddingRight(),
- mapView.getContentPaddingBottom()};
+ return projection.getContentPadding();
}
//
@@ -1334,12 +1423,7 @@ public class MapboxMap {
*/
@UiThread
public void setOnScrollListener(@Nullable OnScrollListener listener) {
- onScrollListener = listener;
- }
-
- // used by MapView
- OnScrollListener getOnScrollListener() {
- return onScrollListener;
+ onRegisterTouchListener.onRegisterScrollListener(listener);
}
/**
@@ -1350,12 +1434,7 @@ public class MapboxMap {
*/
@UiThread
public void setOnFlingListener(@Nullable OnFlingListener listener) {
- onFlingListener = listener;
- }
-
- // used by MapView
- OnFlingListener getOnFlingListener() {
- return onFlingListener;
+ onRegisterTouchListener.onRegisterFlingListener(listener);
}
/**
@@ -1366,12 +1445,7 @@ public class MapboxMap {
*/
@UiThread
public void setOnMapClickListener(@Nullable OnMapClickListener listener) {
- onMapClickListener = listener;
- }
-
- // used by MapView
- OnMapClickListener getOnMapClickListener() {
- return onMapClickListener;
+ onRegisterTouchListener.onRegisterMapClickListener(listener);
}
/**
@@ -1382,12 +1456,7 @@ public class MapboxMap {
*/
@UiThread
public void setOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
- onMapLongClickListener = listener;
- }
-
- // used by MapView
- OnMapLongClickListener getOnMapLongClickListener() {
- return onMapLongClickListener;
+ onRegisterTouchListener.onRegisterMapLongClickListener(listener);
}
/**
@@ -1398,7 +1467,7 @@ public class MapboxMap {
*/
@UiThread
public void setOnInfoWindowClickListener(@Nullable OnInfoWindowClickListener listener) {
- infoWindowManager.setOnInfoWindowClickListener(listener);
+ getAnnotationManager().getInfoWindowManager().setOnInfoWindowClickListener(listener);
}
/**
@@ -1408,7 +1477,7 @@ public class MapboxMap {
*/
@UiThread
public OnInfoWindowClickListener getOnInfoWindowClickListener() {
- return infoWindowManager.getOnInfoWindowClickListener();
+ return getAnnotationManager().getInfoWindowManager().getOnInfoWindowClickListener();
}
/**
@@ -1420,7 +1489,7 @@ public class MapboxMap {
@UiThread
public void setOnInfoWindowLongClickListener(@Nullable OnInfoWindowLongClickListener
listener) {
- infoWindowManager.setOnInfoWindowLongClickListener(listener);
+ getAnnotationManager().getInfoWindowManager().setOnInfoWindowLongClickListener(listener);
}
/**
@@ -1429,11 +1498,11 @@ public class MapboxMap {
* @return Current active InfoWindow long Click Listener
*/
public OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() {
- return infoWindowManager.getOnInfoWindowLongClickListener();
+ return getAnnotationManager().getInfoWindowManager().getOnInfoWindowLongClickListener();
}
public void setOnInfoWindowCloseListener(@Nullable OnInfoWindowCloseListener listener) {
- infoWindowManager.setOnInfoWindowCloseListener(listener);
+ getAnnotationManager().getInfoWindowManager().setOnInfoWindowCloseListener(listener);
}
/**
@@ -1443,7 +1512,7 @@ public class MapboxMap {
*/
@UiThread
public OnInfoWindowCloseListener getOnInfoWindowCloseListener() {
- return infoWindowManager.getOnInfoWindowCloseListener();
+ return getAnnotationManager().getInfoWindowManager().getOnInfoWindowCloseListener();
}
//
@@ -1474,13 +1543,13 @@ public class MapboxMap {
*/
@UiThread
public void setMyLocationEnabled(boolean enabled) {
- if (!mapView.isPermissionsAccepted()) {
+ if (!trackingSettings.isPermissionsAccepted()) {
Timber.e("Could not activate user location tracking: "
+ "user did not accept the permission or permissions were not requested.");
return;
}
myLocationEnabled = enabled;
- mapView.setMyLocationEnabled(enabled);
+ trackingSettings.setMyLocationEnabled(enabled);
}
/**
@@ -1491,7 +1560,7 @@ public class MapboxMap {
@UiThread
@Nullable
public Location getMyLocation() {
- return mapView.getMyLocation();
+ return trackingSettings.getMyLocation();
}
/**
@@ -1504,7 +1573,7 @@ public class MapboxMap {
@UiThread
public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener
listener) {
- mapView.setOnMyLocationChangeListener(listener);
+ trackingSettings.setOnMyLocationChangeListener(listener);
}
/**
@@ -1514,15 +1583,8 @@ public class MapboxMap {
* To unset the callback, use null.
*/
@UiThread
- public void setOnMyLocationTrackingModeChangeListener
- (@Nullable MapboxMap.OnMyLocationTrackingModeChangeListener listener) {
- onMyLocationTrackingModeChangeListener = listener;
- }
-
- // used by MapView
- MapboxMap.OnMyLocationTrackingModeChangeListener getOnMyLocationTrackingModeChangeListener
- () {
- return onMyLocationTrackingModeChangeListener;
+ public void setOnMyLocationTrackingModeChangeListener(@Nullable MapboxMap.OnMyLocationTrackingModeChangeListener listener) {
+ trackingSettings.setOnMyLocationTrackingModeChangeListener(listener);
}
/**
@@ -1532,26 +1594,8 @@ public class MapboxMap {
* To unset the callback, use null.
*/
@UiThread
- public void setOnMyBearingTrackingModeChangeListener
- (@Nullable OnMyBearingTrackingModeChangeListener listener) {
- onMyBearingTrackingModeChangeListener = listener;
- }
-
- // used by MapView
- OnMyBearingTrackingModeChangeListener getOnMyBearingTrackingModeChangeListener() {
- return onMyBearingTrackingModeChangeListener;
- }
-
- MapView getMapView() {
- return mapView;
- }
-
- void setUiSettings(UiSettings uiSettings) {
- this.uiSettings = uiSettings;
- }
-
- void setProjection(Projection projection) {
- this.projection = projection;
+ public void setOnMyBearingTrackingModeChangeListener(@Nullable OnMyBearingTrackingModeChangeListener listener) {
+ trackingSettings.setOnMyBearingTrackingModeChangeListener(listener);
}
//
@@ -1559,13 +1603,6 @@ public class MapboxMap {
//
/**
- * Triggers an invalidation of the map view.
- */
- public void invalidate() {
- mapView.invalidate();
- }
-
- /**
* Takes a snapshot of the map.
*
* @param callback Callback method invoked when the snapshot is taken.
@@ -1573,7 +1610,8 @@ public class MapboxMap {
*/
@UiThread
public void snapshot(@NonNull SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) {
- mapView.snapshot(callback, bitmap);
+ // FIXME 12/02/2016
+ //mapView.snapshot(callback, bitmap);
}
/**
@@ -1583,7 +1621,8 @@ public class MapboxMap {
*/
@UiThread
public void snapshot(@NonNull SnapshotReadyCallback callback) {
- mapView.snapshot(callback, null);
+ // FIXME 12/02/2016
+ //mapView.snapshot(callback, null);
}
/**
@@ -1597,7 +1636,7 @@ public class MapboxMap {
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, @Nullable String...
layerIds) {
- return mapView.getNativeMapView().queryRenderedFeatures(coordinates, layerIds);
+ return nativeMapView.queryRenderedFeatures(coordinates, layerIds);
}
/**
@@ -1611,21 +1650,7 @@ public class MapboxMap {
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, @Nullable String...
layerIds) {
- return mapView.getNativeMapView().queryRenderedFeatures(coordinates, layerIds);
- }
-
- //
- // Innner classes
- //
-
- private class CameraInvalidator implements MapView.OnMapChangedListener {
-
- @Override
- public void onMapChanged(@MapView.MapChange int change) {
- if (change == MapView.REGION_DID_CHANGE_ANIMATED) {
- invalidateCameraPosition();
- }
- }
+ return nativeMapView.queryRenderedFeatures(coordinates, layerIds);
}
//
@@ -1685,6 +1710,20 @@ public class MapboxMap {
}
/**
+ * Interface definition for a callback to be invoked when a user registers an listener that is
+ * related to touch and click events.
+ */
+ interface OnRegisterTouchListener {
+ void onRegisterMapClickListener(OnMapClickListener listener);
+
+ void onRegisterMapLongClickListener(OnMapLongClickListener listener);
+
+ void onRegisterScrollListener(OnScrollListener listener);
+
+ void onRegisterFlingListener(OnFlingListener listener);
+ }
+
+ /**
* Interface definition for a callback to be invoked when the user clicks on the map view.
*
* @see MapboxMap#setOnMapClickListener(OnMapClickListener)
@@ -1939,7 +1978,7 @@ public class MapboxMap {
/**
* Interface definition for a callback to be invoked when the the My Location tracking mode changes.
*
- * @see MapView#setMyLocationTrackingMode(int)
+ * @see TrackingSettings#setMyLocationTrackingMode(int)
*/
public interface OnMyLocationTrackingModeChangeListener {
@@ -1954,7 +1993,7 @@ public class MapboxMap {
/**
* Interface definition for a callback to be invoked when the the My Location tracking mode changes.
*
- * @see MapView#setMyLocationTrackingMode(int)
+ * @see TrackingSettings#setMyLocationTrackingMode(int)
*/
public interface OnMyBearingTrackingModeChangeListener {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index c3d12c4a7a..6189087686 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -9,14 +9,12 @@ import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.DisplayMetrics;
-import timber.log.Timber;
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;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
import com.mapbox.mapboxsdk.offline.OfflineManager;
@@ -32,10 +30,13 @@ import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import timber.log.Timber;
+
// Class that wraps the native methods for convenience
final class NativeMapView {
- boolean destroyed = false;
+ // Flag to indicating destroy was called
+ private boolean destroyed = false;
// Holds the pointer to JNI NativeMapView
private long nativeMapViewPtr = 0;
@@ -43,8 +44,10 @@ final class NativeMapView {
// Used for callbacks
private MapView mapView;
+ // Device density
private final float pixelRatio;
+ // Listeners for Map change events
private CopyOnWriteArrayList<MapView.OnMapChangedListener> onMapChangedListeners;
//
@@ -139,6 +142,9 @@ final class NativeMapView {
}
public void resizeView(int width, int height) {
+ width = (int) (width / pixelRatio);
+ height = (int) (height / pixelRatio);
+
if (width < 0) {
throw new IllegalArgumentException("width cannot be negative.");
}
@@ -208,6 +214,10 @@ final class NativeMapView {
nativeSetStyleUrl(nativeMapViewPtr, url);
}
+ public String getStyleUrl() {
+ return nativeGetStyleUrl(nativeMapViewPtr);
+ }
+
public void setStyleJson(String newStyleJson) {
nativeSetStyleJson(nativeMapViewPtr, newStyleJson);
}
@@ -237,7 +247,7 @@ final class NativeMapView {
}
public void moveBy(double dx, double dy, long duration) {
- nativeMoveBy(nativeMapViewPtr, dx, dy, duration);
+ nativeMoveBy(nativeMapViewPtr, dx / pixelRatio, dy / pixelRatio, duration);
}
public void setLatLng(LatLng latLng) {
@@ -273,7 +283,7 @@ final class NativeMapView {
}
public void scaleBy(double ds, double cx, double cy, long duration) {
- nativeScaleBy(nativeMapViewPtr, ds, cx, cy, duration);
+ nativeScaleBy(nativeMapViewPtr, ds, cx / pixelRatio, cy / pixelRatio, duration);
}
public void setScale(double scale) {
@@ -285,7 +295,7 @@ final class NativeMapView {
}
public void setScale(double scale, double cx, double cy, long duration) {
- nativeSetScale(nativeMapViewPtr, scale, cx, cy, duration);
+ nativeSetScale(nativeMapViewPtr, scale, cx / pixelRatio, cy / pixelRatio, duration);
}
public double getScale() {
@@ -330,11 +340,15 @@ final class NativeMapView {
public void rotateBy(double sx, double sy, double ex, double ey,
long duration) {
- nativeRotateBy(nativeMapViewPtr, sx, sy, ex, ey, duration);
+ nativeRotateBy(nativeMapViewPtr, sx/pixelRatio, sy/pixelRatio, ex, ey, duration);
}
- public void setContentPadding(double top, double left, double bottom, double right) {
- nativeSetContentPadding(nativeMapViewPtr, top, left, bottom, right);
+ public void setContentPadding(int[] padding) {
+ nativeSetContentPadding(nativeMapViewPtr,
+ padding[1] / pixelRatio,
+ padding[0] / pixelRatio,
+ padding[3] / pixelRatio,
+ padding[2] / pixelRatio);
}
public void setBearing(double degrees) {
@@ -346,7 +360,7 @@ final class NativeMapView {
}
public void setBearing(double degrees, double cx, double cy) {
- nativeSetBearingXY(nativeMapViewPtr, degrees, cx, cy);
+ nativeSetBearingXY(nativeMapViewPtr, degrees, cx/pixelRatio, cy/pixelRatio);
}
public double getBearing() {
@@ -443,8 +457,8 @@ final class NativeMapView {
nativeSetReachability(nativeMapViewPtr, status);
}
- public double getMetersPerPixelAtLatitude(double lat, double zoom) {
- return nativeGetMetersPerPixelAtLatitude(nativeMapViewPtr, lat, zoom);
+ public double getMetersPerPixelAtLatitude(double lat) {
+ return nativeGetMetersPerPixelAtLatitude(nativeMapViewPtr, lat, getZoom());
}
public ProjectedMeters projectedMetersForLatLng(LatLng latLng) {
@@ -456,11 +470,13 @@ final class NativeMapView {
}
public PointF pixelForLatLng(LatLng latLng) {
- return nativePixelForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
+ PointF pointF = nativePixelForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude());
+ pointF.set(pointF.x * pixelRatio, pointF.y * pixelRatio);
+ return pointF;
}
public LatLng latLngForPixel(PointF pixel) {
- return nativeLatLngForPixel(nativeMapViewPtr, pixel.x, pixel.y);
+ return nativeLatLngForPixel(nativeMapViewPtr, pixel.x / pixelRatio, pixel.y / pixelRatio);
}
public double getTopOffsetPixelsForAnnotationSymbol(String symbolName) {
@@ -636,6 +652,8 @@ final class NativeMapView {
private native void nativeSetStyleUrl(long nativeMapViewPtr, String url);
+ private native String nativeGetStyleUrl(long nativeMapViewPtr);
+
private native void nativeSetStyleJson(long nativeMapViewPtr, String newStyleJson);
private native String nativeGetStyleJson(long nativeMapViewPtr);
@@ -782,6 +800,14 @@ final class NativeMapView {
private native void nativeSetAPIBaseURL(long nativeMapViewPtr, String baseUrl);
+ int getWidth() {
+ return mapView.getWidth();
+ }
+
+ int getHeight() {
+ return mapView.getHeight();
+ }
+
//
// MapChangeEvents
//
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java
index e06ed38433..5a28d0c7a0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java
@@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.geometry.VisibleRegion;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
/**
* A projection is used to translate between on screen location and geographic coordinates on
@@ -15,15 +16,33 @@ import com.mapbox.mapboxsdk.geometry.VisibleRegion;
*/
public class Projection {
- private final MapView mapView;
- private final float screenDensity;
- private final PointF screenLocationPoint;
+ private final NativeMapView nativeMapView;
+ private int[] contentPadding;
- Projection(@NonNull MapView mapView) {
- this.mapView = mapView;
- this.screenLocationPoint = new PointF();
- this.screenDensity = mapView.getContext() != null ? /* return default if unit test */
- mapView.getContext().getResources().getDisplayMetrics().density : 1.0f;
+ Projection(@NonNull NativeMapView nativeMapView) {
+ this.nativeMapView = nativeMapView;
+ this.contentPadding = new int[]{0, 0, 0, 0};
+ }
+
+ void setContentPadding(int[] contentPadding, int[] userLocationViewPadding) {
+ this.contentPadding = contentPadding;
+
+ int[] padding = new int[]{
+ contentPadding[0] + userLocationViewPadding[0],
+ contentPadding[1] + userLocationViewPadding[1],
+ contentPadding[2] + userLocationViewPadding[2],
+ contentPadding[3] + userLocationViewPadding[3]
+ };
+
+ nativeMapView.setContentPadding(padding);
+ }
+
+ int[] getContentPadding() {
+ return contentPadding;
+ }
+
+ public void invalidateContentPadding(int[] userLocationViewPadding) {
+ setContentPadding(contentPadding, userLocationViewPadding);
}
/**
@@ -37,7 +56,7 @@ public class Projection {
* @return The distance measured in meters.
*/
public double getMetersPerPixelAtLatitude(@FloatRange(from = -90, to = 90) double latitude) {
- return mapView.getMetersPerPixelAtLatitude(latitude);
+ return nativeMapView.getMetersPerPixelAtLatitude(latitude);
}
/**
@@ -50,8 +69,7 @@ public class Projection {
* the given screen point does not intersect the ground plane.
*/
public LatLng fromScreenLocation(PointF point) {
- screenLocationPoint.set(point.x / screenDensity, point.y / screenDensity);
- return mapView.fromNativeScreenLocation(screenLocationPoint);
+ return nativeMapView.latLngForPixel(point);
}
/**
@@ -63,10 +81,10 @@ public class Projection {
public VisibleRegion getVisibleRegion() {
LatLngBounds.Builder builder = new LatLngBounds.Builder();
- float left = mapView.getContentPaddingLeft();
- float right = mapView.getWidth() - mapView.getContentPaddingRight();
- float top = mapView.getContentPaddingTop();
- float bottom = mapView.getHeight() - mapView.getContentPaddingBottom();
+ float left = contentPadding[0];
+ float right = nativeMapView.getWidth() - contentPadding[2];
+ float top = contentPadding[1];
+ float bottom = nativeMapView.getHeight() - contentPadding[3];
LatLng topLeft = fromScreenLocation(new PointF(left, top));
LatLng topRight = fromScreenLocation(new PointF(right, top));
@@ -90,18 +108,14 @@ public class Projection {
* @return A Point representing the screen location in screen pixels.
*/
public PointF toScreenLocation(LatLng location) {
- PointF pointF = mapView.toNativeScreenLocation(location);
- pointF.set(pointF.x * screenDensity, pointF.y * screenDensity);
- return pointF;
+ return nativeMapView.pixelForLatLng(location);
}
- /**
- * Calculates a zoom level based on minimum scale and current scale from MapView
- *
- * @param minScale The minimum scale to calculate the zoom level.
- * @return zoom level that fits the MapView.
- */
- public double calculateZoom(float minScale) {
- return Math.log(mapView.getScale() * minScale) / Math.log(2);
+ float getHeight() {
+ return nativeMapView.getHeight();
+ }
+
+ float getWidth() {
+ return nativeMapView.getWidth();
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
index ac620ca7ba..560f7375c9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
@@ -1,22 +1,30 @@
package com.mapbox.mapboxsdk.maps;
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.graphics.PointF;
+import android.location.Location;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
+import android.support.v4.content.ContextCompat;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
+import com.mapbox.mapboxsdk.location.LocationListener;
+import com.mapbox.mapboxsdk.location.LocationServices;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
/**
* Settings for the user location and bearing tracking of a MapboxMap.
*/
-public class TrackingSettings {
+public final class TrackingSettings {
- private MapView mapView;
- private UiSettings uiSettings;
- private boolean dismissLocationTrackingOnGesture = true;
- private boolean dismissBearingTrackingOnGesture = true;
+ private final MyLocationView myLocationView;
+ private final UiSettings uiSettings;
+ private final FocalPointChangeListener focalPointChangedListener;
+ private LocationListener myLocationListener;
@MyLocationTracking.Mode
private int myLocationTrackingMode;
@@ -24,8 +32,14 @@ public class TrackingSettings {
@MyBearingTracking.Mode
private int myBearingTrackingMode;
- TrackingSettings(@NonNull MapView mapView, UiSettings uiSettings) {
- this.mapView = mapView;
+ private MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener;
+ private MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener;
+ private boolean dismissLocationTrackingOnGesture = true;
+ private boolean dismissBearingTrackingOnGesture = true;
+
+ TrackingSettings(@NonNull MyLocationView myLocationView, UiSettings uiSettings, FocalPointChangeListener focalPointChangedListener) {
+ this.myLocationView = myLocationView;
+ this.focalPointChangedListener = focalPointChangedListener;
this.uiSettings = uiSettings;
}
@@ -45,7 +59,17 @@ public class TrackingSettings {
@UiThread
public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
this.myLocationTrackingMode = myLocationTrackingMode;
- mapView.setMyLocationTrackingMode(myLocationTrackingMode);
+ myLocationView.setMyLocationTrackingMode(myLocationTrackingMode);
+
+ if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
+ focalPointChangedListener.onFocalPointChanged(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY()));
+ } else {
+ focalPointChangedListener.onFocalPointChanged(null);
+ }
+
+ if (onMyLocationTrackingModeChangeListener != null) {
+ onMyLocationTrackingModeChangeListener.onMyLocationTrackingModeChange(myLocationTrackingMode);
+ }
}
/**
@@ -79,7 +103,10 @@ public class TrackingSettings {
@UiThread
public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
this.myBearingTrackingMode = myBearingTrackingMode;
- mapView.setMyBearingTrackingMode(myBearingTrackingMode);
+ myLocationView.setMyBearingTrackingMode(myBearingTrackingMode);
+ if (onMyBearingTrackingModeChangeListener != null) {
+ onMyBearingTrackingModeChangeListener.onMyBearingTrackingModeChange(myBearingTrackingMode);
+ }
}
/**
@@ -220,7 +247,7 @@ public class TrackingSettings {
* @param translate
* @param rotate
*/
- public void resetTrackingModesIfRequired(boolean translate, boolean rotate) {
+ void resetTrackingModesIfRequired(boolean translate, boolean rotate) {
// if tracking is on, and we should dismiss tracking with gestures, and this is a scroll action, turn tracking off
if (translate && !isLocationTrackingDisabled() && isDismissLocationTrackingOnGesture()) {
setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
@@ -232,7 +259,57 @@ public class TrackingSettings {
}
}
- public void resetTrackingModesIfRequired(CameraPosition cameraPosition) {
+ void resetTrackingModesIfRequired(CameraPosition cameraPosition) {
resetTrackingModesIfRequired(cameraPosition.target != null, cameraPosition.bearing != -1);
}
+
+ public void invalidateFocalPointForTracking(MyLocationView myLocationView) {
+ if (!isLocationTrackingDisabled()) {
+ focalPointChangedListener.onFocalPointChanged(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY()));
+ } else {
+ focalPointChangedListener.onFocalPointChanged(null);
+ }
+ }
+
+ void setMyLocationEnabled(boolean enabled) {
+ myLocationView.setEnabled(enabled);
+ }
+
+ Location getMyLocation() {
+ return myLocationView.getLocation();
+ }
+
+ void setOnMyLocationChangeListener(@Nullable final MapboxMap.OnMyLocationChangeListener listener) {
+ if (listener != null) {
+ myLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ if (listener != null) {
+ listener.onMyLocationChange(location);
+ }
+ }
+ };
+ LocationServices.getLocationServices(myLocationView.getContext()).addLocationListener(myLocationListener);
+ } else {
+ LocationServices.getLocationServices(myLocationView.getContext()).removeLocationListener(myLocationListener);
+ myLocationListener = null;
+ }
+ }
+
+ boolean isPermissionsAccepted() {
+ return (ContextCompat.checkSelfPermission(myLocationView.getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) ||
+ ContextCompat.checkSelfPermission(myLocationView.getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
+ }
+
+ void setOnMyLocationTrackingModeChangeListener(MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener) {
+ this.onMyLocationTrackingModeChangeListener = onMyLocationTrackingModeChangeListener;
+ }
+
+ void setOnMyBearingTrackingModeChangeListener(MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener) {
+ this.onMyBearingTrackingModeChangeListener = onMyBearingTrackingModeChangeListener;
+ }
+
+ MyLocationView getMyLocationView(){
+ return myLocationView;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
index 1532bb6745..4aefb0bb7e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
@@ -1,10 +1,15 @@
package com.mapbox.mapboxsdk.maps;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
+import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdate;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import java.util.concurrent.TimeUnit;
@@ -16,18 +21,23 @@ import static com.mapbox.mapboxsdk.maps.MapView.REGION_DID_CHANGE_ANIMATED;
* Responsible for synchronising {@link CameraPosition} state and notifying {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraChangeListener}.
* </p>
*/
-class Transform {
+final class Transform implements MapView.OnMapChangedListener {
- private NativeMapView mapView;
- private MapboxMap mapboxMap;
+ private final NativeMapView mapView;
+ private final MarkerViewManager markerViewManager;
+ private final TrackingSettings trackingSettings;
+ private final MyLocationView myLocationView;
private CameraPosition cameraPosition;
private MapboxMap.CancelableCallback cameraCancelableCallback;
private MapboxMap.OnCameraChangeListener onCameraChangeListener;
- Transform(NativeMapView mapView, MapboxMap mapboxMap) {
+ Transform(NativeMapView mapView, MarkerViewManager markerViewManager, TrackingSettings trackingSettings) {
this.mapView = mapView;
- this.mapboxMap = mapboxMap;
+ this.markerViewManager = markerViewManager;
+ this.trackingSettings = trackingSettings;
+ this.myLocationView = trackingSettings.getMyLocationView();
+ mapView.addOnMapChangedListener(this);
}
//
@@ -43,25 +53,36 @@ class Transform {
}
@UiThread
- final void moveCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) {
+ void updateCameraPosition(@NonNull CameraPosition position) {
+ if (myLocationView != null) {
+ myLocationView.setCameraPosition(position);
+ }
+ markerViewManager.setTilt((float) position.tilt);
+ }
+
+ @Override
+ public void onMapChanged(@MapView.MapChange int change) {
+ if (change == MapView.REGION_DID_CHANGE_ANIMATED) {
+ invalidateCameraPosition();
+ }
+ }
+
+ @UiThread
+ final void moveCamera(MapboxMap mapboxMap, CameraUpdate update, MapboxMap.CancelableCallback callback) {
cameraPosition = update.getCameraPosition(mapboxMap);
- mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(cameraPosition);
+ trackingSettings.resetTrackingModesIfRequired(cameraPosition);
cancelTransitions();
mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom);
-
- // MapChange.REGION_DID_CHANGE_ANIMATED is not called for `jumpTo`
- // invalidate camera position to provide OnCameraChange event.
- mapboxMap.invalidateCameraPosition();
if (callback != null) {
callback.onFinish();
}
}
@UiThread
- final void easeCamera(CameraUpdate update, int durationMs, boolean easingInterpolator, boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) {
+ final void easeCamera(MapboxMap mapboxMap, CameraUpdate update, int durationMs, boolean easingInterpolator, boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) {
cameraPosition = update.getCameraPosition(mapboxMap);
if (resetTrackingMode) {
- mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(cameraPosition);
+ trackingSettings.resetTrackingModesIfRequired(cameraPosition);
}
cancelTransitions();
@@ -83,9 +104,9 @@ class Transform {
}
@UiThread
- final void animateCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
+ final void animateCamera(MapboxMap mapboxMap, CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
cameraPosition = update.getCameraPosition(mapboxMap);
- mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(cameraPosition);
+ trackingSettings.resetTrackingModesIfRequired(cameraPosition);
cancelTransitions();
if (callback != null) {
@@ -140,4 +161,110 @@ class Transform {
private long getDurationNano(long durationMs) {
return durationMs > 0 ? TimeUnit.NANOSECONDS.convert(durationMs, TimeUnit.MILLISECONDS) : 0;
}
+
+ //
+ // non Camera API
+ //
+
+ // Zoom in or out
+
+ double getZoom() {
+ return cameraPosition.zoom;
+ }
+
+ void zoom(boolean zoomIn) {
+ zoom(zoomIn, -1.0f, -1.0f);
+ }
+
+ void zoom(boolean zoomIn, float x, float y) {
+ // Cancel any animation
+ cancelTransitions();
+
+ if (zoomIn) {
+ mapView.scaleBy(2.0, x, y, MapboxConstants.ANIMATION_DURATION);
+ } else {
+ mapView.scaleBy(0.5, x, y, MapboxConstants.ANIMATION_DURATION);
+ }
+ }
+
+ // Direction
+ double getBearing() {
+ double direction = -mapView.getBearing();
+
+ while (direction > 360) {
+ direction -= 360;
+ }
+ while (direction < 0) {
+ direction += 360;
+ }
+
+ return direction;
+ }
+
+ double getRawBearing(){
+ return mapView.getBearing();
+ }
+
+ void setBearing(double bearing) {
+ if (myLocationView != null) {
+ myLocationView.setBearing(bearing);
+ }
+ mapView.setBearing(bearing);
+ }
+
+ void setBearing(double bearing, float focalX, float focalY) {
+ if (myLocationView != null) {
+ myLocationView.setBearing(bearing);
+ }
+ mapView.setBearing(bearing, focalX, focalY);
+ }
+
+
+ //
+ // LatLng / CenterCoordinate
+ //
+
+ LatLng getLatLng() {
+ return mapView.getLatLng();
+ }
+
+ //
+ // Pitch / Tilt
+ //
+
+ double getTilt() {
+ return mapView.getPitch();
+ }
+
+ void setTilt(Double pitch) {
+ if (myLocationView != null) {
+ myLocationView.setTilt(pitch);
+ }
+ markerViewManager.setTilt(pitch.floatValue());
+ mapView.setPitch(pitch, 0);
+ }
+
+ //
+ // Center coordinate
+ //
+
+ LatLng getCenterCoordinate() {
+ return mapView.getLatLng();
+ }
+
+ void setCenterCoordinate(LatLng centerCoordinate) {
+ mapView.setLatLng(centerCoordinate);
+ }
+
+ void setGestureInProgress(boolean gestureInProgress) {
+ mapView.setGestureInProgress(gestureInProgress);
+ }
+
+ void zoomBy(double pow, float x, float y) {
+ mapView.scaleBy(pow, x, y);
+ }
+
+ void moveBy(double offsetX, double offsetY, long duration) {
+ mapView.moveBy(offsetX, offsetY, duration);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
index d6ad80d11e..1523fcefa7 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
@@ -1,23 +1,32 @@
package com.mapbox.mapboxsdk.maps;
+import android.graphics.Color;
import android.graphics.PointF;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
+import android.support.v4.content.ContextCompat;
import android.view.Gravity;
import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.mapbox.mapboxsdk.R;
+import com.mapbox.mapboxsdk.maps.widgets.CompassView;
+import com.mapbox.mapboxsdk.utils.ColorUtils;
/**
* Settings for the user interface of a MapboxMap. To obtain this interface, call getUiSettings().
*/
-public class UiSettings {
-
- private MapView mapView;
+public final class UiSettings {
- private CompassViewSettings compassSettings;
- private ViewSettings logoSettings;
- private ViewSettings attributionSettings;
+ private final FocalPointChangeListener focalPointChangeListener;
+ private final Projection projection;
+ private final CompassView compassView;
+ private final ImageView attributionsView;
+ private final View logoView;
+ private float pixelRatio;
private boolean rotateGesturesEnabled = true;
private boolean rotateGestureChangeAllowed = true;
@@ -35,13 +44,17 @@ public class UiSettings {
private boolean deselectMarkersOnTap = true;
- private PointF focalPoint;
+ private PointF userProvidedFocalPoint;
- UiSettings(@NonNull MapView mapView) {
- this.mapView = mapView;
- this.compassSettings = new CompassViewSettings();
- this.logoSettings = new ViewSettings();
- this.attributionSettings = new ViewSettings();
+ UiSettings(@NonNull Projection projection, @NonNull FocalPointChangeListener listener, @NonNull CompassView compassView, @NonNull ImageView attributionsView, @NonNull View logoView) {
+ this.projection = projection;
+ this.focalPointChangeListener = listener;
+ this.compassView = compassView;
+ this.attributionsView = attributionsView;
+ this.logoView = logoView;
+ if(logoView.getResources()!=null) {
+ this.pixelRatio = logoView.getResources().getDisplayMetrics().density;
+ }
}
/**
@@ -56,8 +69,7 @@ public class UiSettings {
* @param compassEnabled True to enable the compass; false to disable the compass.
*/
public void setCompassEnabled(boolean compassEnabled) {
- compassSettings.setEnabled(compassEnabled);
- mapView.setCompassEnabled(compassEnabled);
+ compassView.setEnabled(compassEnabled);
}
/**
@@ -66,7 +78,7 @@ public class UiSettings {
* @return True if the compass is enabled; false if the compass is disabled.
*/
public boolean isCompassEnabled() {
- return compassSettings.isEnabled();
+ return compassView.isEnabled();
}
/**
@@ -81,8 +93,7 @@ public class UiSettings {
*/
@UiThread
public void setCompassGravity(int gravity) {
- compassSettings.setGravity(gravity);
- mapView.setCompassGravity(gravity);
+ setWidgetGravity(compassView, gravity);
}
/**
@@ -94,8 +105,7 @@ public class UiSettings {
* @param compassFadeFacingNorth True to enable the fading animation; false to disable it
*/
public void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) {
- compassSettings.setFadeFacingNorth(compassFadeFacingNorth);
- mapView.setCompassFadeFacingNorth(compassFadeFacingNorth);
+ compassView.fadeCompassViewFacingNorth(compassFadeFacingNorth);
}
/**
@@ -103,8 +113,8 @@ public class UiSettings {
*
* @return True if the compass will fade, false if it remains visible
*/
- public boolean isCompassFadeWhenFacingNorth(){
- return compassSettings.isFadeFacingNorth();
+ public boolean isCompassFadeWhenFacingNorth() {
+ return compassView.isFadeCompassViewFacingNorth();
}
/**
@@ -113,7 +123,7 @@ public class UiSettings {
* @return The gravity
*/
public int getCompassGravity() {
- return compassSettings.getGravity();
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).gravity;
}
/**
@@ -127,8 +137,7 @@ public class UiSettings {
*/
@UiThread
public void setCompassMargins(int left, int top, int right, int bottom) {
- compassSettings.setMargins(new int[]{left, top, right, bottom});
- mapView.setCompassMargins(left, top, right, bottom);
+ setWidgetMargins(compassView, left, top, right, bottom);
}
/**
@@ -137,7 +146,7 @@ public class UiSettings {
* @return The left margin in pixels
*/
public int getCompassMarginLeft() {
- return compassSettings.getMargins()[0];
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).leftMargin;
}
/**
@@ -146,7 +155,7 @@ public class UiSettings {
* @return The top margin in pixels
*/
public int getCompassMarginTop() {
- return compassSettings.getMargins()[1];
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).topMargin;
}
/**
@@ -155,7 +164,7 @@ public class UiSettings {
* @return The right margin in pixels
*/
public int getCompassMarginRight() {
- return compassSettings.getMargins()[2];
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).rightMargin;
}
/**
@@ -164,7 +173,7 @@ public class UiSettings {
* @return The bottom margin in pixels
*/
public int getCompassMarginBottom() {
- return compassSettings.getMargins()[3];
+ return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).bottomMargin;
}
/**
@@ -176,8 +185,7 @@ public class UiSettings {
* @param enabled True to enable the logo; false to disable the logo.
*/
public void setLogoEnabled(boolean enabled) {
- logoSettings.setEnabled(enabled);
- mapView.setLogoEnabled(enabled);
+ logoView.setVisibility(enabled ? View.VISIBLE : View.GONE);
}
/**
@@ -186,7 +194,7 @@ public class UiSettings {
* @return True if the logo is enabled; false if the logo is disabled.
*/
public boolean isLogoEnabled() {
- return logoSettings.isEnabled();
+ return logoView.getVisibility() == View.VISIBLE;
}
/**
@@ -200,8 +208,7 @@ public class UiSettings {
* @see Gravity
*/
public void setLogoGravity(int gravity) {
- logoSettings.setGravity(gravity);
- mapView.setLogoGravity(gravity);
+ setWidgetGravity(logoView, gravity);
}
/**
@@ -210,7 +217,7 @@ public class UiSettings {
* @return The gravity
*/
public int getLogoGravity() {
- return logoSettings.getGravity();
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).gravity;
}
/**
@@ -223,8 +230,7 @@ public class UiSettings {
* @param bottom The bottom margin in pixels.
*/
public void setLogoMargins(int left, int top, int right, int bottom) {
- logoSettings.setMargins(new int[]{left, top, right, bottom});
- mapView.setLogoMargins(left, top, right, bottom);
+ setWidgetMargins(logoView, left, top, right, bottom);
}
/**
@@ -233,7 +239,7 @@ public class UiSettings {
* @return The left margin in pixels
*/
public int getLogoMarginLeft() {
- return logoSettings.getMargins()[0];
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).leftMargin;
}
/**
@@ -242,7 +248,7 @@ public class UiSettings {
* @return The top margin in pixels
*/
public int getLogoMarginTop() {
- return logoSettings.getMargins()[1];
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).topMargin;
}
/**
@@ -251,7 +257,7 @@ public class UiSettings {
* @return The right margin in pixels
*/
public int getLogoMarginRight() {
- return logoSettings.getMargins()[2];
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).rightMargin;
}
/**
@@ -260,7 +266,7 @@ public class UiSettings {
* @return The bottom margin in pixels
*/
public int getLogoMarginBottom() {
- return logoSettings.getMargins()[3];
+ return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).bottomMargin;
}
/**
@@ -272,8 +278,7 @@ public class UiSettings {
* @param enabled True to enable the attribution; false to disable the attribution.
*/
public void setAttributionEnabled(boolean enabled) {
- attributionSettings.setEnabled(enabled);
- mapView.setAttributionEnabled(enabled ? View.VISIBLE : View.GONE);
+ attributionsView.setVisibility(enabled ? View.VISIBLE : View.GONE);
}
/**
@@ -282,7 +287,7 @@ public class UiSettings {
* @return True if the attribution is enabled; false if the attribution is disabled.
*/
public boolean isAttributionEnabled() {
- return attributionSettings.isEnabled();
+ return attributionsView.getVisibility() == View.VISIBLE;
}
/**
@@ -295,8 +300,7 @@ public class UiSettings {
* @see Gravity
*/
public void setAttributionGravity(int gravity) {
- attributionSettings.setGravity(gravity);
- mapView.setAttributionGravity(gravity);
+ setWidgetGravity(attributionsView, gravity);
}
/**
@@ -305,7 +309,7 @@ public class UiSettings {
* @return The gravity
*/
public int getAttributionGravity() {
- return attributionSettings.getGravity();
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).gravity;
}
/**
@@ -317,8 +321,7 @@ public class UiSettings {
* @param bottom The bottom margin in pixels.
*/
public void setAttributionMargins(int left, int top, int right, int bottom) {
- attributionSettings.setMargins(new int[]{left, top, right, bottom});
- mapView.setAttributionMargins(left, top, right, bottom);
+ setWidgetMargins(attributionsView, left, top, right, bottom);
}
/**
@@ -330,17 +333,12 @@ public class UiSettings {
* @param tintColor Color to tint the attribution.
*/
public void setAttributionTintColor(@ColorInt int tintColor) {
- attributionSettings.setTintColor(tintColor);
- mapView.setAtttibutionTintColor(tintColor);
- }
-
- /**
- * Returns the tint color value of the attribution view.
- *
- * @return The tint color
- */
- public int getAttributionTintColor() {
- return attributionSettings.getTintColor();
+ // Check that the tint color being passed in isn't transparent.
+ if (Color.alpha(tintColor) == 0) {
+ ColorUtils.setTintList(attributionsView, ContextCompat.getColor(attributionsView.getContext(), R.color.mapbox_blue));
+ } else {
+ ColorUtils.setTintList(attributionsView, tintColor);
+ }
}
/**
@@ -349,7 +347,7 @@ public class UiSettings {
* @return The left margin in pixels
*/
public int getAttributionMarginLeft() {
- return attributionSettings.getMargins()[0];
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).leftMargin;
}
/**
@@ -358,7 +356,7 @@ public class UiSettings {
* @return The top margin in pixels
*/
public int getAttributionMarginTop() {
- return attributionSettings.getMargins()[1];
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).topMargin;
}
/**
@@ -367,7 +365,7 @@ public class UiSettings {
* @return The right margin in pixels
*/
public int getAttributionMarginRight() {
- return attributionSettings.getMargins()[2];
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).rightMargin;
}
/**
@@ -376,7 +374,7 @@ public class UiSettings {
* @return The bottom margin in pixels
*/
public int getAttributionMarginBottom() {
- return attributionSettings.getMargins()[3];
+ return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).bottomMargin;
}
/**
@@ -593,8 +591,8 @@ public class UiSettings {
* @param focalPoint the focal point to be used.
*/
public void setFocalPoint(@Nullable PointF focalPoint) {
- this.focalPoint = focalPoint;
- mapView.setFocalPoint(focalPoint);
+ this.userProvidedFocalPoint = focalPoint;
+ focalPointChangeListener.onFocalPointChanged(focalPoint);
}
/**
@@ -603,7 +601,7 @@ public class UiSettings {
* @return The focal point
*/
public PointF getFocalPoint() {
- return focalPoint;
+ return userProvidedFocalPoint;
}
/**
@@ -612,7 +610,7 @@ public class UiSettings {
* @return height in pixels
*/
public float getHeight() {
- return mapView.getMeasuredHeight();
+ return projection.getHeight();
}
/**
@@ -621,15 +619,36 @@ public class UiSettings {
* @return widht in pixels
*/
public float getWidth() {
- return mapView.getMeasuredWidth();
+ return projection.getWidth();
+ }
+
+ float getPixelRatio() {
+ return pixelRatio;
}
/**
* Invalidates the ViewSettings instances shown on top of the MapView
*/
public void invalidate() {
- mapView.setLogoMargins(getLogoMarginLeft(), getLogoMarginTop(), getLogoMarginRight(), getLogoMarginBottom());
- mapView.setCompassMargins(getCompassMarginLeft(), getCompassMarginTop(), getCompassMarginRight(), getCompassMarginBottom());
- mapView.setAttributionMargins(getAttributionMarginLeft(), getAttributionMarginTop(), getAttributionMarginRight(), getAttributionMarginBottom());
+ setLogoMargins(getLogoMarginLeft(), getLogoMarginTop(), getLogoMarginRight(), getLogoMarginBottom());
+ setCompassMargins(getCompassMarginLeft(), getCompassMarginTop(), getCompassMarginRight(), getCompassMarginBottom());
+ setAttributionMargins(getAttributionMarginLeft(), getAttributionMarginTop(), getAttributionMarginRight(), getAttributionMarginBottom());
+ }
+
+ private void setWidgetGravity(@NonNull final View view, int gravity) {
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams();
+ layoutParams.gravity = gravity;
+ view.setLayoutParams(layoutParams);
+ }
+
+ private void setWidgetMargins(@NonNull final View view, int left, int top, int right, int bottom) {
+ int contentPadding[] = projection.getContentPadding();
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams();
+ left += contentPadding[0];
+ top += contentPadding[1];
+ right += contentPadding[2];
+ bottom += contentPadding[3];
+ layoutParams.setMargins(left, top, right, bottom);
+ view.setLayoutParams(layoutParams);
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java
deleted file mode 100644
index 4478978853..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-/**
- * Settings for the overlain views of a MapboxMap. Used by UiSettings.
- */
-class ViewSettings {
-
- private boolean enabled;
- private int gravity;
- private int[] margins;
- private int tintColor;
-
- public ViewSettings() {
- margins = new int[4];
- }
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- public int getGravity() {
- return gravity;
- }
-
- public void setGravity(int gravity) {
- this.gravity = gravity;
- }
-
- public int[] getMargins() {
- return margins;
- }
-
- public void setMargins(int[] margins) {
- this.margins = margins;
- }
-
- public int getTintColor() {
- return tintColor;
- }
-
- public void setTintColor(int tintColor) {
- this.tintColor = tintColor;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
index 5e54354dfa..4d9a60ed66 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
@@ -61,6 +61,7 @@ public final class CompassView extends ImageView implements Runnable {
setLayoutParams(lp);
}
+ // TODO refactor MapboxMap and replace with interface
public void setMapboxMap(@NonNull MapboxMap mapboxMap) {
setOnClickListener(new CompassClickListener(mapboxMap, this));
}
@@ -121,6 +122,10 @@ public final class CompassView extends ImageView implements Runnable {
fadeCompassViewFacingNorth = compassFadeFacingNorth;
}
+ public boolean isFadeCompassViewFacingNorth(){
+ return fadeCompassViewFacingNorth;
+ }
+
@Override
public void run() {
if (isFacingNorth() && fadeCompassViewFacingNorth) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
index 386584141e..1f30734d53 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
@@ -379,6 +379,7 @@ public class MyLocationView extends View {
}
}
+ // TODO refactor MapboxMap out
public void setMapboxMap(MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
this.projection = mapboxMap.getProjection();
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java
index 80bd1b3bef..d8450ff451 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java
@@ -4,14 +4,16 @@ import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.IntRange;
-import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.Projection;
+import com.mapbox.mapboxsdk.maps.TrackingSettings;
/**
* Settings to configure the visual appearance of the MyLocationView.
*/
public class MyLocationViewSettings {
- private MapView mapView;
+ private Projection projection;
+ private TrackingSettings trackingSettings;
private MyLocationView myLocationView;
//
@@ -58,13 +60,14 @@ public class MyLocationViewSettings {
/**
* Creates an instance of MyLocationViewSettings
*
- * @param mapView the MapView that hosts the MyLocationView
+ * @param projection the MapView projection
* @param myLocationView the MyLocationView to apply the settings to
* @see MyLocationView
*/
- public MyLocationViewSettings(MapView mapView, MyLocationView myLocationView) {
- this.mapView = mapView;
+ public MyLocationViewSettings(Projection projection, MyLocationView myLocationView, TrackingSettings trackingSettings) {
+ this.projection = projection;
this.myLocationView = myLocationView;
+ this.trackingSettings = trackingSettings;
}
/**
@@ -208,7 +211,8 @@ public class MyLocationViewSettings {
public void setPadding(int left, int top, int right, int bottom) {
padding = new int[]{left, top, right, bottom};
myLocationView.setContentPadding(padding);
- mapView.invalidateContentPadding();
+ projection.invalidateContentPadding(padding);
+ trackingSettings.invalidateFocalPointForTracking(myLocationView);
}
/**
@@ -257,4 +261,8 @@ public class MyLocationViewSettings {
this.accuracyTintColor = accuracyTintColor;
myLocationView.setAccuracyTint(accuracyTintColor);
}
+
+ public void setTilt(double tilt) {
+ myLocationView.setTilt(tilt);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java
index 22e37ec539..a3545df565 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java
@@ -1,6 +1,16 @@
package com.mapbox.mapboxsdk.telemetry;
+import android.graphics.PointF;
+import android.support.annotation.NonNull;
+
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.Projection;
+
import java.io.Serializable;
+import java.util.Hashtable;
+
+import timber.log.Timber;
/**
* Constants for Telemetry Metadata
@@ -53,7 +63,7 @@ public class MapboxEvent implements Serializable {
public static final String ATTRIBUTE_VENDOR_ID = "vendorId";
public static final String ATTRIBUTE_APP_BUNDLE_ID = "appBundleId";
public static final String ATTRIBUTE_MODEL = "model";
- public static final String ATTRIBUTE_OPERATING_SYSTEM= "operatingSystem";
+ public static final String ATTRIBUTE_OPERATING_SYSTEM = "operatingSystem";
public static final String ATTRIBUTE_ORIENTATION = "orientation";
public static final String ATTRIBUTE_BATTERY_LEVEL = "batteryLevel";
public static final String ATTRIBUTE_PLUGGED_IN = "pluggedIn";
@@ -63,4 +73,71 @@ public class MapboxEvent implements Serializable {
public static final String ATTRIBUTE_CARRIER = "carrier";
public static final String ATTRIBUTE_CELLULAR_NETWORK_TYPE = "cellularNetworkType";
public static final String ATTRIBUTE_WIFI = "wifi";
+
+ /**
+ * Helper method for tracking gesture events
+ *
+ * @param projection Projection of the Map object
+ * @param gestureId Type of Gesture See {@see MapboxEvent#GESTURE_SINGLETAP MapboxEvent#GESTURE_DOUBLETAP MapboxEvent#GESTURE_TWO_FINGER_SINGLETAP MapboxEvent#GESTURE_QUICK_ZOOM MapboxEvent#GESTURE_PAN_START MapboxEvent#GESTURE_PINCH_START MapboxEvent#GESTURE_ROTATION_START MapboxEvent#GESTURE_PITCH_START}
+ * @param xCoordinate Original x screen coordinate at start of gesture
+ * @param yCoordinate Original y screen cooridnate at start of gesture
+ * @param zoom Zoom level to be registered
+ */
+ public static void trackGestureEvent(@NonNull Projection projection, @NonNull String gestureId, float xCoordinate, float yCoordinate, double zoom) {
+ LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
+
+ // NaN and Infinite checks to prevent JSON errors at send to server time
+ if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) {
+ Timber.d("trackGestureEvent() has a NaN lat or lon. Returning.");
+ return;
+ }
+
+ if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) {
+ Timber.d("trackGestureEvent() has an Infinite lat or lon. Returning.");
+ return;
+ }
+
+ Hashtable<String, Object> evt = new Hashtable<>();
+ evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_CLICK);
+ evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
+ evt.put(MapboxEvent.KEY_GESTURE_ID, gestureId);
+ evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude());
+ evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude());
+ evt.put(MapboxEvent.KEY_ZOOM, zoom);
+
+ MapboxEventManager.getMapboxEventManager().pushEvent(evt);
+ }
+
+ /**
+ * Helper method for tracking DragEnd gesture event
+ * See {@see MapboxEvent#TYPE_MAP_DRAGEND}
+ *
+ * @param projection projection of the Map object.
+ * @param xCoordinate Original x screen coordinate at end of drag
+ * @param yCoordinate Orginal y screen coordinate at end of drag
+ * @param zoom Zoom level to be registered
+ */
+ public static void trackGestureDragEndEvent(@NonNull Projection projection, float xCoordinate, float yCoordinate, double zoom) {
+ LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate));
+
+ // NaN and Infinite checks to prevent JSON errors at send to server time
+ if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) {
+ Timber.d("trackGestureDragEndEvent() has a NaN lat or lon. Returning.");
+ return;
+ }
+
+ if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) {
+ Timber.d("trackGestureDragEndEvent() has an Infinite lat or lon. Returning.");
+ return;
+ }
+
+ Hashtable<String, Object> evt = new Hashtable<>();
+ evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_DRAGEND);
+ evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate());
+ evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude());
+ evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude());
+ evt.put(MapboxEvent.KEY_ZOOM, zoom);
+
+ MapboxEventManager.getMapboxEventManager().pushEvent(evt);
+ }
}