summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorLeith Bade <leith@mapbox.com>2015-10-01 15:53:34 +1000
committerLeith Bade <leith@mapbox.com>2015-10-01 19:46:12 +1000
commit4930a40f1f85b4587a76b3f1838afc50874c24de (patch)
treed26788f10cf4c9cd15888ac24cc27f088b836463 /android
parent9fdc36c1a1c91f1fb0db336c2b9b7c61ec94cb20 (diff)
downloadqtlocation-mapboxgl-4930a40f1f85b4587a76b3f1838afc50874c24de.tar.gz
Refactor MapView code to be more maintainable. Implement JavaDocs up to rotation.
Diffstat (limited to 'android')
-rw-r--r--android/java/MapboxGLAndroidSDK/build.gradle7
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java5
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/InfoWindow.java (renamed from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindow.java)7
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/InfoWindowTipView.java (renamed from android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindowTipView.java)2
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java1423
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/package-info.java4
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/res/layout/infowindow.xml2
-rw-r--r--android/java/MapboxGLAndroidSDK/src/main/res/values/arrays.xml1
8 files changed, 823 insertions, 628 deletions
diff --git a/android/java/MapboxGLAndroidSDK/build.gradle b/android/java/MapboxGLAndroidSDK/build.gradle
index 4362291468..48cb99d5da 100644
--- a/android/java/MapboxGLAndroidSDK/build.gradle
+++ b/android/java/MapboxGLAndroidSDK/build.gradle
@@ -75,9 +75,14 @@ android.libraryVariants.all { variant ->
destinationDir = new File(destinationDir, variant.baseName)
source = files(variant.javaCompile.source)
classpath = files(variant.javaCompile.classpath.files) + files(android.bootClasspath)
+ options.windowTitle("Mapbox Android SDK")
+ options.docTitle("Mapbox Android SDK")
+ options.header("<b>Mapbox Android SDK</b>")
+ options.bottom("&copy; 2015 Mapbox. All rights reserved.")
options.links("http://docs.oracle.com/javase/7/docs/api/")
+ // TODO this will fail as package-list file not online, need to use offline
options.links("http://d.android.com/reference/")
- exclude '**/R.html', '**/R.*.html'
+ // TODO exclude generated R, BuildConfig, com.almeros.*
}
}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java
index 2e76a8d9be..111eda083c 100644
--- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/Marker.java
@@ -3,6 +3,7 @@ package com.mapbox.mapboxgl.annotations;
import android.graphics.Point;
import android.view.View;
import com.mapbox.mapboxgl.geometry.LatLng;
+import com.mapbox.mapboxgl.views.InfoWindow;
import com.mapbox.mapboxgl.views.R;
public class Marker extends Annotation {
@@ -138,6 +139,10 @@ public class Marker extends Annotation {
this.sprite = sprite;
}
+ public String getSprite() {
+ return sprite;
+ }
+
public void setTitle(String title) {
this.title = title;
}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindow.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/InfoWindow.java
index 56eae19514..dc4c2a2d19 100644
--- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindow.java
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/InfoWindow.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxgl.annotations;
+package com.mapbox.mapboxgl.views;
import android.content.Context;
import android.graphics.PointF;
@@ -7,8 +7,9 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+
+import com.mapbox.mapboxgl.annotations.Marker;
import com.mapbox.mapboxgl.geometry.LatLng;
-import com.mapbox.mapboxgl.views.MapView;
/**
* A tooltip view
@@ -85,7 +86,7 @@ public class InfoWindow {
mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
PointF coords = mMapView.toScreenLocation(position);
- double y = mMapView.getTopOffsetPixelsForAnnotationSymbol(object.sprite);
+ double y = mMapView.getTopOffsetPixelsForAnnotationSymbol(object.getSprite());
y = y * mMapView.getScreenDensity();
// Flip y coordinate as Android view origin is upper left corner
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindowTipView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/InfoWindowTipView.java
index 657e63a840..b6c849f5c9 100644
--- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/annotations/InfoWindowTipView.java
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/InfoWindowTipView.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxgl.annotations;
+package com.mapbox.mapboxgl.views;
import android.content.Context;
import android.graphics.Canvas;
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java
index aeb744bbc9..1c100c6e98 100644
--- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java
@@ -1,7 +1,9 @@
package com.mapbox.mapboxgl.views;
+import android.app.Activity;
import android.app.ActivityManager;
import android.app.Dialog;
+import android.app.Fragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -26,6 +28,8 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
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;
@@ -47,6 +51,7 @@ 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.TwoFingerGestureDetector;
import com.mapbox.mapboxgl.annotations.Annotation;
@@ -72,13 +77,26 @@ import java.util.Date;
import java.util.Iterator;
import java.util.List;
-// Custom view that shows a Map
-// Based on SurfaceView as we use OpenGL ES to render
+
+/**
+ * <p>A {@link MapView} provides an embeddable map interface, similar to the one provided by Google's Google Maps API.
+ * You use this class to display map information and to manipulate the map contents from your application.
+ * You can center the map on a given coordinate, specify the size of the area you want to display,
+ * and style the features of the map to fit your application’s use case.</p>
+ * <p/>
+ * <p>Use of {@link MapView} requires a Mapbox API access token.
+ * Obtain an access token on the <a href="https://www.mapbox.com/account/apps/">Mapbox account page</a>.</p>
+ * <p/>
+ * <p><b>Warning:</b> Please note that you are responsible for getting permission to use the map data,
+ * and for ensuring your use adheres to the relevant terms of use.</p>
+ */
public class MapView extends FrameLayout implements LocationListener {
//
// Static members
//
+
+ // Used for logging
private static final String TAG = "MapView";
// Used for animation
@@ -98,7 +116,6 @@ public class MapView extends FrameLayout implements LocationListener {
private static final String STATE_STYLE_CLASSES = "styleClasses";
private static final String STATE_DEFAULT_TRANSITION_DURATION = "defaultTransitionDuration";
private static final String STATE_MY_LOCATION_ENABLED = "myLocationEnabled";
- private static final String STATE_USER_LOCATION_TRACKING_MODE = "userLocationTrackingMode";
private static final String STATE_COMPASS_ENABLED = "compassEnabled";
private static final String STATE_COMPASS_GRAVITY = "compassGravity";
private static final String STATE_COMPASS_MARGIN_LEFT = "compassMarginLeft";
@@ -122,15 +139,10 @@ public class MapView extends FrameLayout implements LocationListener {
private static final float DIMENSION_SIXTEEN_DP = 16f;
private static final float DIMENSION_SEVENTYSIX_DP = 76f;
+ // Used to select "Improve this map" link in the attribution dialog
+ // Index into R.arrays.attribution_links
private static final int ATTRIBUTION_INDEX_IMPROVE_THIS_MAP = 2;
- /**
- * Every annotation that has been added to the map.
- */
- private List<Annotation> mAnnotations = new ArrayList<>();
- private List<Annotation> mAnnotationsNearLastTap = new ArrayList<>();
- private Annotation mSelectedAnnotation = null;
-
//
// Instance members
//
@@ -156,25 +168,19 @@ public class MapView extends FrameLayout implements LocationListener {
// Used to track trackball long presses
private TrackballLongPressTimeOut mCurrentTrackballLongPressTimeOut;
+ // Receives changes to network connectivity
private ConnectivityReceiver mConnectivityReceiver;
// Holds the context
private Context mContext;
- // Used for GPS / Location
- private boolean mIsMyLocationEnabled = false;
+ // Used for user location
private LostApiClient mLocationClient;
private LocationRequest mLocationRequest;
private ImageView mGpsMarker;
private Location mGpsLocation;
- public enum UserLocationTrackingMode {
- NONE, FOLLOW, FOLLOW_BEARING
- }
- private UserLocationTrackingMode mUserLocationTrackingMode = UserLocationTrackingMode.FOLLOW;
-
- // Used for compass
- private boolean mIsCompassEnabled = true;
+ // Used for the compass
private ImageView mCompassView;
private SensorManager mSensorManager;
private Sensor mSensorAccelerometer;
@@ -188,139 +194,188 @@ public class MapView extends FrameLayout implements LocationListener {
private float mCompassBearing;
private boolean mCompassValid = false;
- // Used for MapboxLogo
+ // Used for displaying annotation markers
+ // Every annotation that has been added to the map
+ private List<Annotation> mAnnotations = new ArrayList<>();
+ private List<Annotation> mAnnotationsNearLastTap = new ArrayList<>();
+ private Annotation mSelectedAnnotation = null;
+
+ // Used for the Mapbox Logo
private ImageView mLogoView;
// Used for attributions control
private ImageView mAttributionsView;
- // Used for map toggle mode
- private long t0 = new Date().getTime();
-
- // Used to manage Event Listeners
+ // Used to manage MapChange event listeners
private ArrayList<OnMapChangedListener> mOnMapChangedListener;
+ // Used to manage fling and scroll event listeners
+ private OnFlingListener onFlingListener;
+ private OnScrollListener onScrollListener;
+
+ //
+ // Properties
+ //
+
+ // These are properties with setters/getters, saved in onSaveInstanceState and XML attributes
+ private boolean mZoomEnabled = true;
+ private boolean mScrollEnabled = true;
+ private boolean mRotateEnabled = true;
+ private String mStyleUrl;
+ private boolean mIsMyLocationEnabled = false;
+ private boolean mIsCompassEnabled = true;
+
+ //
+ // Enums
+ //
+
+ /**
+ * Map change event types received by
+ * {@link com.mapbox.mapboxgl.views.MapView.OnMapChangedListener#onMapChanged(MapChange)}
+ */
public enum MapChange {
- MapChangeNullChange(-1),
- MapChangeRegionWillChange(0),
- MapChangeRegionWillChangeAnimated(1),
- MapChangeRegionIsChanging(2),
- MapChangeRegionDidChange(3),
- MapChangeRegionDidChangeAnimated(4),
- MapChangeWillStartLoadingMap(5),
- MapChangeDidFinishLoadingMap(6),
- MapChangeDidFailLoadingMap(7),
- MapChangeWillStartRenderingFrame(8),
- MapChangeDidFinishRenderingFrame(9),
- MapChangeDidFinishRenderingFrameFullyRendered(10),
- MapChangeWillStartRenderingMap(11),
- MapChangeDidFinishRenderingMap(12),
- MapChangeDidFinishRenderingMapFullyRendered(13);
-
- private int value;
-
- private MapChange(int value) {
- this.value = value;
- }
-
- public static MapChange fromInteger(int value) {
+ /**
+ * TODO pull descriptions from C++
+ */
+ RegionWillChange,
+ RegionWillChangeAnimated,
+ RegionIsChanging,
+ RegionDidChange,
+ RegionDidChangeAnimated,
+ WillStartLoadingMap,
+ DidFinishLoadingMap,
+ DidFailLoadingMap,
+ WillStartRenderingFrame,
+ DidFinishRenderingFrame,
+ DidFinishRenderingFrameFullyRendered,
+ WillStartRenderingMap,
+ DidFinishRenderingMap,
+ DidFinishRenderingMapFullyRendered;
+
+ // Converts the C++ values from include/mpbgl/map/view.hpp MapChange to Java enum values
+ private static MapChange fromInteger(int value) {
switch (value) {
- case -1:
- return MapChange.MapChangeNullChange;
case 0:
- return MapChange.MapChangeRegionWillChange;
+ return MapChange.RegionWillChange;
case 1:
- return MapChange.MapChangeRegionWillChangeAnimated;
+ return MapChange.RegionWillChangeAnimated;
case 2:
- return MapChange.MapChangeRegionIsChanging;
+ return MapChange.RegionIsChanging;
case 3:
- return MapChange.MapChangeRegionDidChange;
+ return MapChange.RegionDidChange;
case 4:
- return MapChange.MapChangeRegionDidChangeAnimated;
+ return MapChange.RegionDidChangeAnimated;
case 5:
- return MapChange.MapChangeWillStartLoadingMap;
+ return MapChange.WillStartLoadingMap;
case 6:
- return MapChange.MapChangeDidFinishLoadingMap;
+ return MapChange.DidFinishLoadingMap;
case 7:
- return MapChange.MapChangeDidFailLoadingMap;
+ return MapChange.DidFailLoadingMap;
case 8:
- return MapChange.MapChangeWillStartRenderingFrame;
+ return MapChange.WillStartRenderingFrame;
case 9:
- return MapChange.MapChangeDidFinishRenderingFrame;
+ return MapChange.DidFinishRenderingFrame;
case 10:
- return MapChange.MapChangeDidFinishRenderingFrameFullyRendered;
+ return MapChange.DidFinishRenderingFrameFullyRendered;
case 11:
- return MapChange.MapChangeWillStartRenderingMap;
+ return MapChange.WillStartRenderingMap;
case 12:
- return MapChange.MapChangeDidFinishRenderingMap;
+ return MapChange.DidFinishRenderingMap;
case 13:
- return MapChange.MapChangeDidFinishRenderingMapFullyRendered;
+ return MapChange.DidFinishRenderingMapFullyRendered;
default:
return null;
}
}
}
+ //
+ // Interfaces
+ //
+
+ /**
+ * Interface definition for a callback to be invoked when the map is flinged.
+ */
public interface OnFlingListener {
+ /**
+ * Called when the map is flinged.
+ */
void onFling();
}
+ /**
+ * Interface definition for a callback to be invoked when the map is scrolled.
+ */
public interface OnScrollListener {
+ /**
+ * Called when the map is scrolled.
+ */
void onScroll();
}
- private OnFlingListener onFlingListener;
- private OnScrollListener onScrollListener;
-
- public void setOnScrollListener(OnScrollListener onScrollListener) {
- this.onScrollListener = onScrollListener;
- }
-
- public void setOnFlingListener(OnFlingListener onFlingListener) {
- this.onFlingListener = onFlingListener;
- }
-
- //
- // Properties
- //
-
- private boolean mZoomEnabled = true;
- private boolean mScrollEnabled = true;
- private boolean mRotateEnabled = true;
- private String mStyleUrl;
-
//
// Constructors
//
- // Called when no properties are being set from XML
- public MapView(Context context) {
- super(context);
- initialize(context, null);
- }
-
- public MapView(Context context, @NonNull String accessToken) {
+ /**
+ * Simple constructor to use when creating a {@link MapView} from code using the default map style.
+ *
+ * @param context The {@link Context} of the {@link android.app.Activity}
+ * or {@link android.app.Fragment} the {@link MapView} is running in.
+ * @param accessToken Your Mapbox access token.
+ */
+ // TODO default map style
+ @UiThread
+ public MapView(@NonNull Context context, @NonNull String accessToken) {
super(context);
+ if (accessToken == null) {
+ throw new NullPointerException("accessToken is null");
+ }
initialize(context, null);
setAccessToken(accessToken);
}
- public MapView(Context context, @NonNull String accessToken, String styleUrl) {
+ /**
+ * Simple constructor to use when creating a {@link MapView} from code using the provided map style URL.
+ *
+ * @param context The {@link Context} of the {@link android.app.Activity}
+ * or {@link android.app.Fragment} the {@link MapView} is running in.
+ * @param accessToken Your public Mapbox access token. Used to load map styles and tiles.
+ * @param styleUrl A URL to the map style initially displayed.
+ */
+ @UiThread
+ public MapView(@NonNull Context context, @NonNull String accessToken, @NonNull String styleUrl) {
super(context);
+ if (accessToken == null) {
+ throw new NullPointerException("accessToken is null");
+ }
+ if (styleUrl == null) {
+ throw new NullPointerException("styleUrl is null");
+ }
initialize(context, null);
setAccessToken(accessToken);
setStyleUrl(styleUrl);
}
- // Called when properties are being set from XML
- public MapView(Context context, AttributeSet attrs) {
+ // Constructor that is called when inflating a view from XML.
+
+ /**
+ * Do not call from code.
+ */
+ @UiThread
+ public MapView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs);
}
- // Called when properties are being set from XML
- public MapView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
+ // Constructor that is called when inflating a view from XML.
+
+ /**
+ * Do not call from code.
+ */
+ @UiThread
+ public MapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
initialize(context, attrs);
}
@@ -330,22 +385,26 @@ public class MapView extends FrameLayout implements LocationListener {
// Common initialization code goes here
private void initialize(Context context, AttributeSet attrs) {
+ if (context == null) {
+ throw new NullPointerException("context is null");
+ }
// Save the context
mContext = context;
+ // Create the TextureView
TextureView textureView = new TextureView(mContext);
addView(textureView);
- // Check if we are in Eclipse UI editor
+ // Check if we are in Android Studio UI editor to avoid error in layout preview
if (isInEditMode()) {
return;
}
// Get the screen's density
mScreenDensity = context.getResources().getDisplayMetrics().density;
- int tenDp = (int)(10 * mScreenDensity);
- int sixteenDp = (int)(16 * mScreenDensity);
+ int tenDp = (int) (10 * mScreenDensity);
+ int sixteenDp = (int) (16 * mScreenDensity);
// Get the cache path
String cachePath = context.getCacheDir().getAbsolutePath();
@@ -355,13 +414,15 @@ public class MapView extends FrameLayout implements LocationListener {
// Create the NativeMapView
int availableProcessors = Runtime.getRuntime().availableProcessors();
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
- ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ ActivityManager activityManager = (ActivityManager) context
+ .getSystemService(Context.ACTIVITY_SERVICE);
activityManager.getMemoryInfo(memoryInfo);
long maxMemory = memoryInfo.availMem;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
maxMemory = memoryInfo.totalMem;
}
- mNativeMapView = new NativeMapView(this, cachePath, dataPath, apkPath, mScreenDensity, availableProcessors, maxMemory);
+ mNativeMapView = new
+ NativeMapView(this, cachePath, dataPath, apkPath, mScreenDensity, availableProcessors, maxMemory);
// Ensure this view is interactable
setClickable(true);
@@ -383,42 +444,47 @@ public class MapView extends FrameLayout implements LocationListener {
// Shows the zoom controls
// But not when in Eclipse UI editor
if (!isInEditMode()) {
- if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) {
+ if (!context.getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) {
mZoomButtonsController = new ZoomButtonsController(this);
mZoomButtonsController.setZoomSpeed(ANIMATION_DURATION);
mZoomButtonsController.setOnZoomListener(new OnZoomListener());
}
// Check current connection status
- ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ ConnectivityManager connectivityManager = (ConnectivityManager) context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
boolean isConnected = (activeNetwork != null) && activeNetwork.isConnectedOrConnecting();
onConnectivityChanged(isConnected);
}
- // Setup Location Services
+ // Setup location aervices
mLocationClient = new LostApiClient.Builder(getContext()).build();
mLocationRequest = LocationRequest.create()
.setInterval(1000)
.setSmallestDisplacement(1)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
- // Setup User Location UI
+ // Setup user location UI
mGpsMarker = new ImageView(getContext());
mGpsMarker.setImageResource(R.drawable.location_marker);
mGpsMarker.setVisibility(View.INVISIBLE);
addView(mGpsMarker);
- // Setup Compass
+ // Setup compass
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mCompassListener = new CompassListener();
+ // Setup compass UI
mCompassView = new ImageView(mContext);
mCompassView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.compass));
mCompassView.setContentDescription(getResources().getString(R.string.compassContentDescription));
- LayoutParams lp = new FrameLayout.LayoutParams((int)(48 * mScreenDensity), (int)(48 * mScreenDensity));
+ LayoutParams lp = new FrameLayout.LayoutParams(
+ (int) (48 * mScreenDensity),
+ (int) (48 * mScreenDensity));
mCompassView.setLayoutParams(lp);
mCompassView.setVisibility(View.INVISIBLE);
addView(mCompassView);
@@ -428,7 +494,8 @@ public class MapView extends FrameLayout implements LocationListener {
mLogoView = new ImageView(mContext);
mLogoView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_logo_mapbox));
mLogoView.setContentDescription(getResources().getString(R.string.mapboxIconContentDescription));
- LayoutParams logoParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ LayoutParams logoParams = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mLogoView.setLayoutParams(logoParams);
addView(mLogoView);
@@ -439,8 +506,10 @@ public class MapView extends FrameLayout implements LocationListener {
int attrPadding = (int) (DIMENSION_SEVEN_DP * mScreenDensity);
mAttributionsView.setPadding(attrPadding, attrPadding, attrPadding, attrPadding);
mAttributionsView.setAdjustViewBounds(true);
- mAttributionsView.setContentDescription(getResources().getString(R.string.attributionsIconContentDescription));
- LayoutParams attrParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ mAttributionsView.setContentDescription(getResources()
+ .getString(R.string.attributionsIconContentDescription));
+ LayoutParams attrParams = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mAttributionsView.setLayoutParams(attrParams);
addView(mAttributionsView);
mAttributionsView.setOnClickListener(new AttributionOnClickListener(this));
@@ -456,7 +525,8 @@ public class MapView extends FrameLayout implements LocationListener {
double centerLongitude = typedArray.getFloat(R.styleable.MapView_centerLongitude, 0.0f);
LatLng centerCoordinate = new LatLng(centerLatitude, centerLongitude);
setCenterCoordinate(centerCoordinate);
- setZoomLevel(typedArray.getFloat(R.styleable.MapView_zoomLevel, 0.0f)); // need to set zoom level first because of limitation on rotating when zoomed out
+ // need to set zoom level first because of limitation on rotating when zoomed out
+ setZoomLevel(typedArray.getFloat(R.styleable.MapView_zoomLevel, 0.0f));
setDirection(typedArray.getFloat(R.styleable.MapView_direction, 0.0f));
setZoomEnabled(typedArray.getBoolean(R.styleable.MapView_zoomEnabled, true));
setScrollEnabled(typedArray.getBoolean(R.styleable.MapView_scrollEnabled, true));
@@ -469,7 +539,8 @@ public class MapView extends FrameLayout implements LocationListener {
setAccessToken(typedArray.getString(R.styleable.MapView_accessToken));
}
if (typedArray.getString(R.styleable.MapView_styleClasses) != null) {
- List<String> styleClasses = Arrays.asList(typedArray.getString(R.styleable.MapView_styleClasses).split("\\s*,\\s*"));
+ List<String> styleClasses = Arrays.asList(typedArray
+ .getString(R.styleable.MapView_styleClasses).split("\\s*,\\s*"));
for (String styleClass : styleClasses) {
if (styleClass.length() == 0) {
styleClasses.remove(styleClass);
@@ -500,6 +571,7 @@ public class MapView extends FrameLayout implements LocationListener {
, typedArray.getDimension(R.styleable.MapView_attributionMarginRight, DIMENSION_SEVEN_DP)
, typedArray.getDimension(R.styleable.MapView_attributionMarginBottom, DIMENSION_SEVEN_DP));
+ // User location
setMyLocationEnabled(typedArray.getBoolean(R.styleable.MapView_myLocationEnabled, false));
} finally {
typedArray.recycle();
@@ -507,152 +579,291 @@ public class MapView extends FrameLayout implements LocationListener {
}
//
- // Annotations
+ // Lifecycle events
//
- public void setSprite(String symbol, float scale, Bitmap bitmap) {
- if(bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
- bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
- }
- ByteBuffer buffer = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight());
- bitmap.copyPixelsToBuffer(buffer);
+ /**
+ * You must call this method from the parent's {@link android.app.Activity#onCreate(Bundle)} or
+ * {@link android.app.Fragment#onCreate(Bundle)}
+ *
+ * @param savedInstanceState Pass in the parent's savedInstanceState.
+ */
+ @UiThread
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ if (savedInstanceState != null) {
+ setCenterCoordinate((LatLng) savedInstanceState.getParcelable(STATE_CENTER_COORDINATE));
+ // need to set zoom level first because of limitation on rotating when zoomed out
+ setZoomLevel(savedInstanceState.getDouble(STATE_ZOOM_LEVEL));
+ setDirection(savedInstanceState.getDouble(STATE_CENTER_DIRECTION));
+ setDirection(savedInstanceState.getDouble(STATE_DIRECTION));
+ setZoomEnabled(savedInstanceState.getBoolean(STATE_ZOOM_ENABLED));
+ setScrollEnabled(savedInstanceState.getBoolean(STATE_SCROLL_ENABLED));
+ setRotateEnabled(savedInstanceState.getBoolean(STATE_ROTATE_ENABLED));
+ setDebugActive(savedInstanceState.getBoolean(STATE_DEBUG_ACTIVE));
+ setStyleUrl(savedInstanceState.getString(STATE_STYLE_URL));
+ setAccessToken(savedInstanceState.getString(STATE_ACCESS_TOKEN));
+ List<String> appliedStyleClasses = savedInstanceState.getStringArrayList(STATE_STYLE_CLASSES);
+ if (!appliedStyleClasses.isEmpty()) {
+ setStyleClasses(appliedStyleClasses);
+ }
+ mNativeMapView.setDefaultTransitionDuration(
+ savedInstanceState.getLong(STATE_DEFAULT_TRANSITION_DURATION));
+ setMyLocationEnabled(savedInstanceState.getBoolean(STATE_MY_LOCATION_ENABLED));
- mNativeMapView.setSprite(symbol, bitmap.getWidth(), bitmap.getHeight(), scale, buffer.array());
- }
+ // Compass
+ setCompassEnabled(savedInstanceState.getBoolean(STATE_COMPASS_ENABLED));
+ setCompassGravity(savedInstanceState.getInt(STATE_COMPASS_GRAVITY));
+ setCompassMargins(savedInstanceState.getInt(STATE_COMPASS_MARGIN_LEFT)
+ , savedInstanceState.getInt(STATE_COMPASS_MARGIN_TOP)
+ , savedInstanceState.getInt(STATE_COMPASS_MARGIN_RIGHT)
+ , savedInstanceState.getInt(STATE_COMPASS_MARGIN_BOTTOM));
- public Marker addMarker(MarkerOptions markerOptions) {
- Marker marker = markerOptions.getMarker();
- long id = mNativeMapView.addMarker(marker);
- marker.setId(id); // the annotation needs to know its id
- marker.setMapView(this); // the annotation needs to know which map view it is in
- mAnnotations.add(marker);
- return marker;
- }
+ // Logo
+ setLogoGravity(savedInstanceState.getInt(STATE_LOGO_GRAVITY));
+ setLogoMargins(savedInstanceState.getInt(STATE_LOGO_MARGIN_LEFT)
+ , savedInstanceState.getInt(STATE_LOGO_MARGIN_TOP)
+ , savedInstanceState.getInt(STATE_LOGO_MARGIN_RIGHT)
+ , savedInstanceState.getInt(STATE_LOGO_MARGIN_BOTTOM));
- public Polyline addPolyline(PolylineOptions polylineOptions) {
- Polyline polyline = polylineOptions.getPolyline();
- long id = mNativeMapView.addPolyline(polyline);
- polyline.setId(id);
- polyline.setMapView(this);
- mAnnotations.add(polyline);
- return polyline;
- }
+ // Attribution
+ setAttributionGravity(savedInstanceState.getInt(STATE_ATTRIBUTION_GRAVITY));
+ setAttributionMargins(savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_LEFT)
+ , savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_TOP)
+ , savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_RIGHT)
+ , savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_BOTTOM));
+ }
- public Polygon addPolygon(PolygonOptions polygonOptions) {
- Polygon polygon = polygonOptions.getPolygon();
- long id = mNativeMapView.addPolygon(polygon);
- polygon.setId(id);
- polygon.setMapView(this);
- mAnnotations.add(polygon);
- return polygon;
+ // Force a check for an access token
+ validateAccessToken(getAccessToken());
+
+ // Initialize EGL
+ mNativeMapView.initializeDisplay();
+ mNativeMapView.initializeContext();
+
+ // Add annotation deselection listener
+ addOnMapChangedListener(new OnMapChangedListener() {
+ @Override
+ public void onMapChanged(MapChange change) {
+ if (change.equals(MapChange.RegionWillChange) ||
+ change.equals(MapChange.RegionWillChangeAnimated)) {
+ deselectAnnotation();
+ }
+ }
+ });
}
- public List<Polygon> addPolygons(List<PolygonOptions> polygonOptions) {
- List<Polygon> polygons = new ArrayList<>();
- for(PolygonOptions popts : polygonOptions) {
- polygons.add(popts.getPolygon());
+ /**
+ * You must call this method from the parent's {@link android.app.Activity#onSaveInstanceState(Bundle)}
+ * or {@link android.app.Fragment#onSaveInstanceState(Bundle)}
+ *
+ * @param outState Pass in the parent's outState.
+ */
+ @UiThread
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ if (outState == null) {
+ throw new NullPointerException("outState is null");
}
- long[] ids = mNativeMapView.addPolygons(polygons);
+ outState.putParcelable(STATE_CENTER_COORDINATE, getCenterCoordinate());
+ // need to set zoom level first because of limitation on rotating when zoomed out
+ outState.putDouble(STATE_ZOOM_LEVEL, getZoomLevel());
+ outState.putDouble(STATE_CENTER_DIRECTION, getDirection());
+ outState.putBoolean(STATE_ZOOM_ENABLED, mZoomEnabled);
+ outState.putBoolean(STATE_SCROLL_ENABLED, mScrollEnabled);
+ outState.putBoolean(STATE_ROTATE_ENABLED, mRotateEnabled);
+ outState.putBoolean(STATE_DEBUG_ACTIVE, isDebugActive());
+ outState.putString(STATE_STYLE_URL, mStyleUrl);
+ outState.putString(STATE_ACCESS_TOKEN, getAccessToken());
+ outState.putStringArrayList(STATE_STYLE_CLASSES, new ArrayList<>(getStyleClasses()));
+ outState.putLong(STATE_DEFAULT_TRANSITION_DURATION, mNativeMapView.getDefaultTransitionDuration());
+ outState.putBoolean(STATE_MY_LOCATION_ENABLED, isMyLocationEnabled());
- for(int i=0; i < polygons.size(); i++) {
- polygons.get(i).setId(ids[i]);
- polygons.get(i).setMapView(this);
- mAnnotations.add(polygons.get(i));
- }
+ // Compass
+ LayoutParams compassParams = (LayoutParams) mCompassView.getLayoutParams();
+ outState.putBoolean(STATE_COMPASS_ENABLED, isCompassEnabled());
+ outState.putInt(STATE_COMPASS_GRAVITY, compassParams.gravity);
+ outState.putInt(STATE_COMPASS_MARGIN_LEFT, compassParams.leftMargin);
+ outState.putInt(STATE_COMPASS_MARGIN_TOP, compassParams.topMargin);
+ outState.putInt(STATE_COMPASS_MARGIN_BOTTOM, compassParams.bottomMargin);
+ outState.putInt(STATE_COMPASS_MARGIN_RIGHT, compassParams.rightMargin);
- return Collections.unmodifiableList(polygons);
+ // Logo
+ LayoutParams logoParams = (LayoutParams) mLogoView.getLayoutParams();
+ outState.putInt(STATE_LOGO_GRAVITY, logoParams.gravity);
+ outState.putInt(STATE_LOGO_MARGIN_LEFT, logoParams.leftMargin);
+ outState.putInt(STATE_LOGO_MARGIN_TOP, logoParams.topMargin);
+ outState.putInt(STATE_LOGO_MARGIN_RIGHT, logoParams.rightMargin);
+ outState.putInt(STATE_LOGO_MARGIN_BOTTOM, logoParams.bottomMargin);
+
+ // Attribution
+ LayoutParams attrParams = (LayoutParams) mAttributionsView.getLayoutParams();
+ outState.putInt(STATE_ATTRIBUTION_GRAVITY, attrParams.gravity);
+ outState.putInt(STATE_ATTRIBUTION_MARGIN_LEFT, attrParams.leftMargin);
+ outState.putInt(STATE_ATTRIBUTION_MARGIN_TOP, attrParams.topMargin);
+ outState.putInt(STATE_ATTRIBUTION_MARGIN_RIGHT, attrParams.rightMargin);
+ outState.putInt(STATE_ATTRIBUTION_MARGIN_BOTTOM, attrParams.bottomMargin);
}
- private void removeAnnotationsWithId(long annotationId){
- for (Iterator<Annotation> iterator = mAnnotations.iterator(); iterator.hasNext();) {
- Annotation annotation = iterator.next();
- if (annotation instanceof Marker) {
- ((Marker)annotation).hideInfoWindow();
- }
- if (annotation.getId() == annotationId) {
- iterator.remove();
- }
- }
+ /**
+ * You must call this method from the parent's {@link Activity#onDestroy()} or {@link Fragment#onDestroy()}
+ */
+ @UiThread
+ public void onDestroy() {
+ mNativeMapView.terminateContext();
+ mNativeMapView.terminateDisplay();
}
- public void removeAnnotation(Annotation annotation) {
- if (annotation instanceof Marker) {
- ((Marker)annotation).hideInfoWindow();
- }
- long id = annotation.getId();
- mNativeMapView.removeAnnotation(id);
- mAnnotations.remove(annotation);
+ /**
+ * You must call this method from the parent's {@link Activity#onStart()} or {@link Fragment#onStart()}
+ */
+ @UiThread
+ public void onStart() {
}
- public void removeAnnotation(long annotationId) {
- mNativeMapView.removeAnnotation(annotationId);
- removeAnnotationsWithId(annotationId);
+ /**
+ * You must call this method from the parent's {@link Activity#onStop()} or {@link Fragment#onStop()}
+ */
+ @UiThread
+ public void onStop() {
}
- public void removeAnnotations() {
- long[] ids = new long[mAnnotations.size()];
- for(int i = 0; i < mAnnotations.size(); i++) {
- Annotation annotation = mAnnotations.get(i);
- long id = annotation.getId();
- ids[i] = id;
- if (annotation instanceof Marker) {
- ((Marker)annotation).hideInfoWindow();
- }
+ /**
+ * You must call this method from the parent's {@link Activity#onPause()} or {@link Fragment#onPause()}
+ */
+ @UiThread
+ public void onPause() {
+ // Register for connectivity changes
+ getContext().unregisterReceiver(mConnectivityReceiver);
+ mConnectivityReceiver = null;
+
+ if (mIsMyLocationEnabled) {
+ toggleGps(false);
}
- mNativeMapView.removeAnnotations(ids);
- mAnnotations.clear();
- }
- public List<Annotation> getAnnotations() {
- return Collections.unmodifiableList(mAnnotations);
+ mNativeMapView.pause();
}
- public List<Annotation> getAnnotationsInBounds(BoundingBox bbox) {
- List<Annotation> annotations = new ArrayList<>();
- long[] ids = mNativeMapView.getAnnotationsInBounds(bbox);
- List<Long> idsList = new ArrayList<>();
- for(int i = 0; i < ids.length; i++) {
- idsList.add(new Long(ids[i]));
- }
- for(int i = 0; i < mAnnotations.size(); i++) {
- Annotation annotation = mAnnotations.get(i);
- if (annotation instanceof Marker && idsList.contains(annotation.getId())) {
- annotations.add(annotation);
- }
+ /**
+ * You must call this method from the parent's {@link Activity#onResume()} or {@link Fragment#onResume()}
+ */
+ @UiThread
+ public void onResume() {
+ // Register for connectivity changes
+ mConnectivityReceiver = new ConnectivityReceiver();
+ mContext.registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
+
+ if (mIsMyLocationEnabled) {
+ toggleGps(true);
}
- return annotations;
+
+ mNativeMapView.resume();
+ }
+
+ /**
+ * You must call this method from the parent's {@link Activity#onLowMemory()} or {@link Fragment#onLowMemory()}
+ */
+ @UiThread
+ public void onLowMemory() {
+ mNativeMapView.onLowMemory();
}
//
- // Property methods
+ // Position
//
+ /**
+ * Returns the current coordinate at the center of the map view.
+ *
+ * @return The current coordinate.
+ */
+ @UiThread
+ @NonNull
public LatLng getCenterCoordinate() {
return mNativeMapView.getLatLng();
}
- public void setCenterCoordinate(LatLng centerCoordinate) {
+ /**
+ * <p>Centers the map on a new coordinate immediately without changing the zoom level.</p>
+ * <p>If you want to animate the change, use {@link MapView#setCenterCoordinate(LatLng, boolean)}.</p>
+ *
+ * @param centerCoordinate The new coordinate.
+ */
+ @UiThread
+ public void setCenterCoordinate(@NonNull LatLng centerCoordinate) {
setCenterCoordinate(centerCoordinate, false);
}
- public void setCenterCoordinate(LatLng centerCoordinate, boolean animated) {
+ /**
+ * Centers the map on a new coordinate without changing the zoom level and optionally animates the change.
+ *
+ * @param centerCoordinate The new coordinate.
+ * @param animated If true, animates the change. If false, immediately changes the map.
+ */
+ @UiThread
+ public void setCenterCoordinate(@NonNull LatLng centerCoordinate, boolean animated) {
+ if (centerCoordinate == null) {
+ throw new NullPointerException("centerCoordinate is null");
+ }
long duration = animated ? ANIMATION_DURATION : 0;
mNativeMapView.cancelTransitions();
mNativeMapView.setLatLng(centerCoordinate, duration);
}
- public void setCenterCoordinate(LatLngZoom centerCoordinate) {
+
+ /**
+ * <p>Centers the map on a new coordinate immediately while changing the current zoom level.</p>
+ * <p>If you want to animate the change, use {@link MapView#setCenterCoordinate(LatLngZoom, boolean)}.</p>
+ *
+ * @param centerCoordinate The new coordinate and zoom level.
+ */
+ @UiThread
+ public void setCenterCoordinate(@NonNull LatLngZoom centerCoordinate) {
setCenterCoordinate(centerCoordinate, false);
}
- public void setCenterCoordinate(LatLngZoom centerCoordinate,
+ /**
+ * Centers the map on a new coordinate while changing the zoom level and optionally animates the change.
+ *
+ * @param centerCoordinate The new coordinate and zoom level.
+ * @param animated If true, animates the change. If false, immediately changes the map.
+ */
+ @UiThread
+ public void setCenterCoordinate(@NonNull LatLngZoom centerCoordinate,
boolean animated) {
+ if (centerCoordinate == null) {
+ throw new NullPointerException("centerCoordinate is null");
+ }
long duration = animated ? ANIMATION_DURATION : 0;
mNativeMapView.cancelTransitions();
mNativeMapView.setLatLngZoom(centerCoordinate, duration);
}
+ /**
+ * Returns whether the user may scroll around the map.
+ *
+ * @return If true, scrolling is enabled. If false, scrolling is disabled.
+ */
+ @UiThread
+ public boolean isScrollEnabled() {
+ return mScrollEnabled;
+ }
+
+ /**
+ * <p>Changes whether the user may scroll around the map.</p>
+ * <p>This setting controls only user interactions with the map. If you set the value to false,
+ * you may still change the map location programmatically.</p>
+ *
+ * @param scrollEnabled If true, scrolling is enabled. If false, scrolling is disabled.
+ */
+ @UiThread
+ public void setScrollEnabled(boolean scrollEnabled) {
+ this.mScrollEnabled = scrollEnabled;
+ }
+
+ //
+ // Rotation
+ //
+
public double getDirection() {
double direction = -mNativeMapView.getBearing();
@@ -686,6 +897,18 @@ public class MapView extends FrameLayout implements LocationListener {
mNativeMapView.resetNorth();
}
+ public boolean isRotateEnabled() {
+ return mRotateEnabled;
+ }
+
+ public void setRotateEnabled(boolean rotateEnabled) {
+ this.mRotateEnabled = rotateEnabled;
+ }
+
+ //
+ // Scale
+ //
+
public double getZoomLevel() {
return mNativeMapView.getZoom();
}
@@ -712,21 +935,26 @@ public class MapView extends FrameLayout implements LocationListener {
}
}
- public boolean isScrollEnabled() {
- return mScrollEnabled;
+ // Zoom in or out
+ private void zoom(boolean zoomIn) {
+ zoom(zoomIn, -1.0f, -1.0f);
}
- public void setScrollEnabled(boolean scrollEnabled) {
- this.mScrollEnabled = scrollEnabled;
- }
+ private void zoom(boolean zoomIn, float x, float y) {
+ // Cancel any animation
+ mNativeMapView.cancelTransitions();
- public boolean isRotateEnabled() {
- return mRotateEnabled;
+ if (zoomIn) {
+ mNativeMapView.scaleBy(2.0, x / mScreenDensity, y / mScreenDensity, ANIMATION_DURATION);
+ } else {
+ // TODO two finger tap zoom out
+ mNativeMapView.scaleBy(0.5, x / mScreenDensity, y / mScreenDensity, ANIMATION_DURATION);
+ }
}
- public void setRotateEnabled(boolean rotateEnabled) {
- this.mRotateEnabled = rotateEnabled;
- }
+ //
+ // Debug
+ //
public boolean isDebugActive() {
return mNativeMapView.getDebug() || mNativeMapView.getCollisionDebug();
@@ -742,18 +970,14 @@ public class MapView extends FrameLayout implements LocationListener {
mNativeMapView.toggleCollisionDebug();
}
- public UserLocationTrackingMode getUserLocationTrackingMode() {
- return mUserLocationTrackingMode;
- }
-
- public void setUserLocationTrackingMode(UserLocationTrackingMode userLocationTrackingMode) {
- this.mUserLocationTrackingMode = userLocationTrackingMode;
- }
-
public boolean isFullyLoaded() {
return mNativeMapView.isFullyLoaded();
}
+ //
+ // Styling
+ //
+
public void setStyleUrl(String url) {
mStyleUrl = url;
mNativeMapView.setStyleUrl(url);
@@ -763,22 +987,6 @@ public class MapView extends FrameLayout implements LocationListener {
return mStyleUrl;
}
- private void validateAccessToken(@NonNull String accessToken) {
-
- if (TextUtils.isEmpty(accessToken) || (!accessToken.startsWith("pk.") && !accessToken.startsWith("sk."))) {
- throw new RuntimeException("Using MapView requires setting a valid access token. See the README.md");
- }
- }
-
- public void setAccessToken(@NonNull String accessToken) {
- validateAccessToken(accessToken);
- mNativeMapView.setAccessToken(accessToken);
- }
-
- public String getAccessToken() {
- return mNativeMapView.getAccessToken();
- }
-
public List<String> getStyleClasses() {
return Collections.unmodifiableList(mNativeMapView.getClasses());
}
@@ -814,6 +1022,30 @@ public class MapView extends FrameLayout implements LocationListener {
setStyleClasses(styleClasses);
}
+ //
+ // Access token
+ //
+
+ private void validateAccessToken(@NonNull String accessToken) {
+
+ if (TextUtils.isEmpty(accessToken) || (!accessToken.startsWith("pk.") && !accessToken.startsWith("sk."))) {
+ throw new RuntimeException("Using MapView requires setting a valid access token. See the README.md");
+ }
+ }
+
+ public void setAccessToken(@NonNull String accessToken) {
+ validateAccessToken(accessToken);
+ mNativeMapView.setAccessToken(accessToken);
+ }
+
+ public String getAccessToken() {
+ return mNativeMapView.getAccessToken();
+ }
+
+ //
+ // Projection
+ //
+
public LatLng fromScreenLocation(PointF point) {
return mNativeMapView.latLngForPixel(new PointF(point.x / mScreenDensity, point.y / mScreenDensity));
}
@@ -823,170 +1055,195 @@ public class MapView extends FrameLayout implements LocationListener {
return new PointF(point.x * mScreenDensity, point.y * mScreenDensity);
}
- public double getTopOffsetPixelsForAnnotationSymbol(@NonNull String symbolName) {
- return mNativeMapView.getTopOffsetPixelsForAnnotationSymbol(symbolName);
+ //
+ // Annotations
+ //
+
+ public void setSprite(String symbol, float scale, Bitmap bitmap) {
+ if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
+ bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
+ }
+ ByteBuffer buffer = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight());
+ bitmap.copyPixelsToBuffer(buffer);
+
+ mNativeMapView.setSprite(symbol, bitmap.getWidth(), bitmap.getHeight(), scale, buffer.array());
}
- /**
- * Common Screen Density
- * @return Screen Density
- */
- public float getScreenDensity() {
- return mScreenDensity;
+ public Marker addMarker(MarkerOptions markerOptions) {
+ Marker marker = markerOptions.getMarker();
+ long id = mNativeMapView.addMarker(marker);
+ marker.setId(id); // the annotation needs to know its id
+ marker.setMapView(this); // the annotation needs to know which map view it is in
+ mAnnotations.add(marker);
+ return marker;
}
- //
- // Lifecycle events
- //
+ public Polyline addPolyline(PolylineOptions polylineOptions) {
+ Polyline polyline = polylineOptions.getPolyline();
+ long id = mNativeMapView.addPolyline(polyline);
+ polyline.setId(id);
+ polyline.setMapView(this);
+ mAnnotations.add(polyline);
+ return polyline;
+ }
- // Called when we need to restore instance state
- // Must be called from Activity onCreate
- public void onCreate(Bundle savedInstanceState) {
- if (savedInstanceState != null) {
- setCenterCoordinate((LatLng) savedInstanceState.getParcelable(STATE_CENTER_COORDINATE));
- setZoomLevel(savedInstanceState.getDouble(STATE_ZOOM_LEVEL)); // need to set zoom level first because of limitation on rotating when zoomed out
- setDirection(savedInstanceState.getDouble(STATE_CENTER_DIRECTION));
- setDirection(savedInstanceState.getDouble(STATE_DIRECTION));
- setZoomEnabled(savedInstanceState.getBoolean(STATE_ZOOM_ENABLED));
- setScrollEnabled(savedInstanceState.getBoolean(STATE_SCROLL_ENABLED));
- setRotateEnabled(savedInstanceState.getBoolean(STATE_ROTATE_ENABLED));
- setDebugActive(savedInstanceState.getBoolean(STATE_DEBUG_ACTIVE));
- setStyleUrl(savedInstanceState.getString(STATE_STYLE_URL));
- setAccessToken(savedInstanceState.getString(STATE_ACCESS_TOKEN));
- List<String> appliedStyleClasses = savedInstanceState.getStringArrayList(STATE_STYLE_CLASSES);
- if (!appliedStyleClasses.isEmpty()) {
- setStyleClasses(appliedStyleClasses);
- }
- mNativeMapView.setDefaultTransitionDuration(savedInstanceState.getLong(STATE_DEFAULT_TRANSITION_DURATION));
- setMyLocationEnabled(savedInstanceState.getBoolean(STATE_MY_LOCATION_ENABLED));
- setUserLocationTrackingMode((UserLocationTrackingMode) savedInstanceState.getSerializable(STATE_USER_LOCATION_TRACKING_MODE));
+ public Polygon addPolygon(PolygonOptions polygonOptions) {
+ Polygon polygon = polygonOptions.getPolygon();
+ long id = mNativeMapView.addPolygon(polygon);
+ polygon.setId(id);
+ polygon.setMapView(this);
+ mAnnotations.add(polygon);
+ return polygon;
+ }
- // Compass
- setCompassEnabled(savedInstanceState.getBoolean(STATE_COMPASS_ENABLED));
- setCompassGravity(savedInstanceState.getInt(STATE_COMPASS_GRAVITY));
- setCompassMargins(savedInstanceState.getInt(STATE_COMPASS_MARGIN_LEFT)
- , savedInstanceState.getInt(STATE_COMPASS_MARGIN_TOP)
- , savedInstanceState.getInt(STATE_COMPASS_MARGIN_RIGHT)
- , savedInstanceState.getInt(STATE_COMPASS_MARGIN_BOTTOM));
+ public List<Polygon> addPolygons(List<PolygonOptions> polygonOptions) {
+ List<Polygon> polygons = new ArrayList<>();
+ for (PolygonOptions popts : polygonOptions) {
+ polygons.add(popts.getPolygon());
+ }
- // Logo
- setLogoGravity(savedInstanceState.getInt(STATE_LOGO_GRAVITY));
- setLogoMargins(savedInstanceState.getInt(STATE_LOGO_MARGIN_LEFT)
- , savedInstanceState.getInt(STATE_LOGO_MARGIN_TOP)
- , savedInstanceState.getInt(STATE_LOGO_MARGIN_RIGHT)
- , savedInstanceState.getInt(STATE_LOGO_MARGIN_BOTTOM));
+ long[] ids = mNativeMapView.addPolygons(polygons);
- // Attribution
- setAttributionGravity(savedInstanceState.getInt(STATE_ATTRIBUTION_GRAVITY));
- setAttributionMargins(savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_LEFT)
- , savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_TOP)
- , savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_RIGHT)
- , savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_BOTTOM));
+ for (int i = 0; i < polygons.size(); i++) {
+ polygons.get(i).setId(ids[i]);
+ polygons.get(i).setMapView(this);
+ mAnnotations.add(polygons.get(i));
}
- // Force a check for an access token
- validateAccessToken(getAccessToken());
-
- mNativeMapView.initializeDisplay();
- mNativeMapView.initializeContext();
+ return Collections.unmodifiableList(polygons);
+ }
- addOnMapChangedListener(new OnMapChangedListener() {
- @Override
- public void onMapChanged(MapChange change) {
- if (change.equals(MapChange.MapChangeRegionWillChange) || change.equals(MapChange.MapChangeRegionWillChangeAnimated)) {
- deselectAnnotation();
- }
+ private void removeAnnotationsWithId(long annotationId) {
+ for (Iterator<Annotation> iterator = mAnnotations.iterator(); iterator.hasNext(); ) {
+ Annotation annotation = iterator.next();
+ if (annotation instanceof Marker) {
+ ((Marker) annotation).hideInfoWindow();
}
- });
+ if (annotation.getId() == annotationId) {
+ iterator.remove();
+ }
+ }
}
- // Called when we need to save instance state
- // Must be called from Activity onSaveInstanceState
- public void onSaveInstanceState(Bundle outState) {
- outState.putParcelable(STATE_CENTER_COORDINATE, getCenterCoordinate());
- outState.putDouble(STATE_ZOOM_LEVEL, getZoomLevel()); // need to set zoom level first because of limitation on rotating when zoomed out
- outState.putDouble(STATE_CENTER_DIRECTION, getDirection());
- outState.putBoolean(STATE_ZOOM_ENABLED, mZoomEnabled);
- outState.putBoolean(STATE_SCROLL_ENABLED, mScrollEnabled);
- outState.putBoolean(STATE_ROTATE_ENABLED, mRotateEnabled);
- outState.putBoolean(STATE_DEBUG_ACTIVE, isDebugActive());
- outState.putString(STATE_STYLE_URL, mStyleUrl);
- outState.putString(STATE_ACCESS_TOKEN, getAccessToken());
- outState.putStringArrayList(STATE_STYLE_CLASSES, new ArrayList<>(getStyleClasses()));
- outState.putLong(STATE_DEFAULT_TRANSITION_DURATION, mNativeMapView.getDefaultTransitionDuration());
- outState.putBoolean(STATE_MY_LOCATION_ENABLED, isMyLocationEnabled());
- outState.putSerializable(STATE_USER_LOCATION_TRACKING_MODE, getUserLocationTrackingMode());
+ public void removeAnnotation(Annotation annotation) {
+ if (annotation instanceof Marker) {
+ ((Marker) annotation).hideInfoWindow();
+ }
+ long id = annotation.getId();
+ mNativeMapView.removeAnnotation(id);
+ mAnnotations.remove(annotation);
+ }
- // Compass
- LayoutParams compassParams = (LayoutParams) mCompassView.getLayoutParams();
- outState.putBoolean(STATE_COMPASS_ENABLED, isCompassEnabled());
- outState.putInt(STATE_COMPASS_GRAVITY, compassParams.gravity );
- outState.putInt(STATE_COMPASS_MARGIN_LEFT, compassParams.leftMargin);
- outState.putInt(STATE_COMPASS_MARGIN_TOP, compassParams.topMargin);
- outState.putInt(STATE_COMPASS_MARGIN_BOTTOM, compassParams.bottomMargin);
- outState.putInt(STATE_COMPASS_MARGIN_RIGHT, compassParams.rightMargin);
+ public void removeAnnotation(long annotationId) {
+ mNativeMapView.removeAnnotation(annotationId);
+ removeAnnotationsWithId(annotationId);
+ }
- // Logo
- LayoutParams logoParams = (LayoutParams) mLogoView.getLayoutParams();
- outState.putInt(STATE_LOGO_GRAVITY, logoParams.gravity);
- outState.putInt(STATE_LOGO_MARGIN_LEFT, logoParams.leftMargin);
- outState.putInt(STATE_LOGO_MARGIN_TOP, logoParams.topMargin);
- outState.putInt(STATE_LOGO_MARGIN_RIGHT, logoParams.rightMargin);
- outState.putInt(STATE_LOGO_MARGIN_BOTTOM, logoParams.bottomMargin);
+ public void removeAnnotations() {
+ long[] ids = new long[mAnnotations.size()];
+ for (int i = 0; i < mAnnotations.size(); i++) {
+ Annotation annotation = mAnnotations.get(i);
+ long id = annotation.getId();
+ ids[i] = id;
+ if (annotation instanceof Marker) {
+ ((Marker) annotation).hideInfoWindow();
+ }
+ }
+ mNativeMapView.removeAnnotations(ids);
+ mAnnotations.clear();
+ }
- // Attribution
- LayoutParams attrParams = (LayoutParams) mAttributionsView.getLayoutParams();
- outState.putInt(STATE_ATTRIBUTION_GRAVITY, attrParams.gravity);
- outState.putInt(STATE_ATTRIBUTION_MARGIN_LEFT, attrParams.leftMargin);
- outState.putInt(STATE_ATTRIBUTION_MARGIN_TOP, attrParams.topMargin);
- outState.putInt(STATE_ATTRIBUTION_MARGIN_RIGHT, attrParams.rightMargin);
- outState.putInt(STATE_ATTRIBUTION_MARGIN_BOTTOM, attrParams.bottomMargin);
+ public List<Annotation> getAnnotations() {
+ return Collections.unmodifiableList(mAnnotations);
}
- // Called when we need to clean up
- // Must be called from Activity onDestroy
- public void onDestroy() {
- mNativeMapView.terminateContext();
- mNativeMapView.terminateDisplay();
+ public List<Annotation> getAnnotationsInBounds(BoundingBox bbox) {
+ List<Annotation> annotations = new ArrayList<>();
+ long[] ids = mNativeMapView.getAnnotationsInBounds(bbox);
+ List<Long> idsList = new ArrayList<>();
+ for (int i = 0; i < ids.length; i++) {
+ idsList.add(new Long(ids[i]));
+ }
+ for (int i = 0; i < mAnnotations.size(); i++) {
+ Annotation annotation = mAnnotations.get(i);
+ if (annotation instanceof Marker && idsList.contains(annotation.getId())) {
+ annotations.add(annotation);
+ }
+ }
+ return annotations;
}
- // Called when we need to create the GL context
- // Must be called from Activity onStart
- public void onStart() {
+ // Used by InfoWindow
+ double getTopOffsetPixelsForAnnotationSymbol(@NonNull String symbolName) {
+ return mNativeMapView.getTopOffsetPixelsForAnnotationSymbol(symbolName);
}
- // Called when we need to terminate the GL context
- // Must be called from Activity onPause
- public void onStop() {
+ // Used by InfoWindow
+ float getScreenDensity() {
+ return mScreenDensity;
}
- // Called when we need to stop the render thread
- // Must be called from Activity onPause
- public void onPause() {
- // Register for connectivity changes
- getContext().unregisterReceiver(mConnectivityReceiver);
- mConnectivityReceiver = null;
+ private void selectAnnotation(Annotation annotation) {
- if (mIsMyLocationEnabled) {
- toggleGps(false);
+ if (annotation == null) {
+ return;
}
- mNativeMapView.pause();
+ if (annotation == mSelectedAnnotation) {
+ return;
+ }
+
+ if (annotation instanceof Marker) {
+ // Need to deselect any currently selected annotation first
+ deselectAnnotation();
+
+ ((Marker) annotation).showInfoWindow();
+ mSelectedAnnotation = annotation;
+ }
}
- // Called when we need to start the render thread
- // Must be called from Activity onResume
+ private void deselectAnnotation() {
+ if (mSelectedAnnotation != null && mSelectedAnnotation instanceof Marker) {
+ Marker marker = (Marker) mSelectedAnnotation;
+ if (marker.isInfoWindowShown()) {
+ marker.hideInfoWindow();
+ mSelectedAnnotation = null;
+ }
+ }
+ }
- public void onResume() {
- // Register for connectivity changes
- mConnectivityReceiver = new ConnectivityReceiver();
- mContext.registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
- if (mIsMyLocationEnabled) {
- toggleGps(true);
+ //
+ // Rendering
+ //
+
+ // Called when the map needs to be rerendered
+ // Called via JNI from NativeMapView
+ protected void onInvalidate() {
+ synchronized (mDirty) {
+ if (!mDirty) {
+ mDirty = true;
+ postRender();
+ }
}
+ }
- mNativeMapView.resume();
+ private void postRender() {
+ Runnable mRunnable = new Runnable() {
+ @Override
+ public void run() {
+ updateCompass();
+ updateGpsMarker();
+ mNativeMapView.renderSync();
+ mDirty = false;
+ }
+ };
+
+ if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ postOnAnimation(mRunnable);
+ } else {
+ postDelayed(mRunnable, 1000 / 60);
+ }
}
public void onSizeChanged(int width, int height, int oldw, int oldh) {
@@ -1001,7 +1258,7 @@ public class MapView extends FrameLayout implements LocationListener {
// Called when the native surface texture has been created
// Must do all EGL/GL ES initialization here
@Override
- public void onSurfaceTextureAvailable (SurfaceTexture surface, int width, int height) {
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mNativeMapView.createSurface(new Surface(surface));
mNativeMapView.resizeFramebuffer(width, height);
}
@@ -1009,7 +1266,7 @@ public class MapView extends FrameLayout implements LocationListener {
// Called when the native surface texture has been destroyed
// Must do all EGL/GL ES destruction here
@Override
- public boolean onSurfaceTextureDestroyed (SurfaceTexture surface) {
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
mNativeMapView.destroySurface();
return true;
}
@@ -1017,17 +1274,21 @@ public class MapView extends FrameLayout implements LocationListener {
// Called when the format or size of the native surface texture has been changed
// Must handle window resizing here.
@Override
- public void onSurfaceTextureSizeChanged (SurfaceTexture surface, int width, int height) {
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
mNativeMapView.resizeFramebuffer(width, height);
}
// Not used
@Override
- public void onSurfaceTextureUpdated (SurfaceTexture surface) {
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Do nothing
}
}
+ //
+ // View events
+ //
+
// Called when view is no longer connected
@Override
protected void onDetachedFromWindow() {
@@ -1051,37 +1312,10 @@ public class MapView extends FrameLayout implements LocationListener {
}
}
- // Called when the system is running low on memory
- // Must be called from Activity onLowMemory
- public void onLowMemory() {
- mNativeMapView.onLowMemory();
- }
-
- //
- // Draw events
- //
-
//
- // Input events
+ // Touch events
//
- // 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
- mNativeMapView.cancelTransitions();
-
- if (zoomIn) {
- mNativeMapView.scaleBy(2.0, x / mScreenDensity, y / mScreenDensity, ANIMATION_DURATION);
- } else {
- // TODO two finger tap zoom out
- mNativeMapView.scaleBy(0.5, x / mScreenDensity, y / mScreenDensity, ANIMATION_DURATION);
- }
- }
-
// Called when user touches the screen, all positions are absolute
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
@@ -1185,17 +1419,17 @@ public class MapView extends FrameLayout implements LocationListener {
PointF tapPoint = new PointF(x, y);
- float toleranceWidth = 40 * mScreenDensity;
+ float toleranceWidth = 40 * mScreenDensity;
float toleranceHeight = 60 * mScreenDensity;
RectF tapRect = new RectF(tapPoint.x - toleranceWidth / 2, tapPoint.y + 2 * toleranceHeight / 3,
- tapPoint.x + toleranceWidth / 2, tapPoint.y - 1 * toleranceHeight / 3);
+ tapPoint.x + toleranceWidth / 2, tapPoint.y - 1 * toleranceHeight / 3);
List<LatLng> corners = Arrays.asList(
- fromScreenLocation(new PointF(tapRect.left, tapRect.bottom)),
- fromScreenLocation(new PointF(tapRect.left, tapRect.top)),
- fromScreenLocation(new PointF(tapRect.right, tapRect.top)),
- fromScreenLocation(new PointF(tapRect.right, tapRect.bottom))
+ fromScreenLocation(new PointF(tapRect.left, tapRect.bottom)),
+ fromScreenLocation(new PointF(tapRect.left, tapRect.top)),
+ fromScreenLocation(new PointF(tapRect.right, tapRect.top)),
+ fromScreenLocation(new PointF(tapRect.right, tapRect.bottom))
);
BoundingBox tapBounds = BoundingBox.fromLatLngs(corners);
@@ -1211,30 +1445,22 @@ public class MapView extends FrameLayout implements LocationListener {
// first, sort for comparison and iteration
Collections.sort(nearbyAnnotations);
- if (nearbyAnnotations == mAnnotationsNearLastTap)
- {
+ if (nearbyAnnotations == mAnnotationsNearLastTap) {
// the selection candidates haven't changed; cycle through them
- if (mSelectedAnnotation != null && (mSelectedAnnotation.getId() == mAnnotationsNearLastTap.get(mAnnotationsNearLastTap.size() - 1).getId()))
- {
+ if (mSelectedAnnotation != null && (mSelectedAnnotation.getId() == mAnnotationsNearLastTap.get(mAnnotationsNearLastTap.size() - 1).getId())) {
// the selected annotation is the last in the set; cycle back to the first
// note: this could be the selected annotation if only one in set
newSelectedAnnotationID = mAnnotationsNearLastTap.get(0).getId();
- }
- else if (mSelectedAnnotation != null)
- {
+ } else if (mSelectedAnnotation != null) {
// otherwise increment the selection through the candidates
long currentID = mSelectedAnnotation.getId();
long result = mAnnotationsNearLastTap.indexOf(mSelectedAnnotation);
newSelectedAnnotationID = mAnnotationsNearLastTap.get((int) result + 1).getId();
- }
- else
- {
+ } else {
// no current selection; select the first one
newSelectedAnnotationID = mAnnotationsNearLastTap.get(0).getId();
}
- }
- else
- {
+ } else {
// start tracking a new set of nearby annotations
mAnnotationsNearLastTap = nearbyAnnotations;
@@ -1242,7 +1468,7 @@ public class MapView extends FrameLayout implements LocationListener {
newSelectedAnnotationID = mAnnotationsNearLastTap.get(0).getId();
}
- } else {
+ } else {
// there are no nearby annotations; deselect if necessary
newSelectedAnnotationID = -1;
}
@@ -1302,7 +1528,7 @@ public class MapView extends FrameLayout implements LocationListener {
mNativeMapView.moveBy(velocityX * duration / 2.0 / mScreenDensity, velocityY * duration / 2.0 / mScreenDensity, (long) (duration * 1000.0f));
- if(onFlingListener != null){
+ if (onFlingListener != null) {
onFlingListener.onFling();
}
@@ -1324,7 +1550,7 @@ public class MapView extends FrameLayout implements LocationListener {
// Scroll the map
mNativeMapView.moveBy(-distanceX / mScreenDensity, -distanceY / mScreenDensity);
- if(onScrollListener != null){
+ if (onScrollListener != null) {
onScrollListener.onScroll();
}
@@ -1486,6 +1712,10 @@ public class MapView extends FrameLayout implements LocationListener {
}
}
+ //
+ // Input events
+ //
+
// Called when the user presses a key, also called for repeating keys held
// down
@Override
@@ -1761,7 +1991,7 @@ public class MapView extends FrameLayout implements LocationListener {
}
//
- // Action events
+ // Connectivity events
//
// This class handles connectivity changes
@@ -1783,42 +2013,9 @@ public class MapView extends FrameLayout implements LocationListener {
}
//
- // Accessibility events
- //
-
- //
// Map events
//
- // Called when the map needs to be rerendered
- // Called via JNI from NativeMapView
- protected void onInvalidate() {
- synchronized (mDirty) {
- if (!mDirty) {
- mDirty = true;
- postRender();
- }
- }
- }
-
- private void postRender() {
- Runnable mRunnable = new Runnable() {
- @Override
- public void run() {
- updateCompass();
- updateGpsMarker();
- mNativeMapView.renderSync();
- mDirty = false;
- }
- };
-
- if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- postOnAnimation(mRunnable);
- } else {
- postDelayed(mRunnable, 1000 / 60);
- }
- }
-
/**
* Defines callback for events OnMapChange
*/
@@ -1828,6 +2025,7 @@ public class MapView extends FrameLayout implements LocationListener {
/**
* Add an OnMapChangedListner
+ *
* @param listener Listener to add
*/
public void addOnMapChangedListener(@NonNull OnMapChangedListener listener) {
@@ -1838,6 +2036,7 @@ public class MapView extends FrameLayout implements LocationListener {
/**
* Remove an OnMapChangedListener
+ *
* @param listener Listener to remove
*/
public void removeOnMapChangedListener(@NonNull OnMapChangedListener listener) {
@@ -1887,13 +2086,24 @@ public class MapView extends FrameLayout implements LocationListener {
}
}
- // Google Maps Inspired API
+ public void setOnScrollListener(OnScrollListener onScrollListener) {
+ this.onScrollListener = onScrollListener;
+ }
+
+ public void setOnFlingListener(OnFlingListener onFlingListener) {
+ this.onFlingListener = onFlingListener;
+ }
+
+ //
+ // User location
+ //
/**
* Gets the status of the my-location layer.
+ *
* @return True if the my-location layer is enabled, false otherwise.
*/
- public final boolean isMyLocationEnabled () {
+ public final boolean isMyLocationEnabled() {
return mIsMyLocationEnabled;
}
@@ -1902,23 +2112,26 @@ public class MapView extends FrameLayout implements LocationListener {
* While enabled, the my-location layer continuously draws an indication of a user's current
* location and bearing, and displays UI controls that allow a user to interact with their
* location (for example, to enable or disable camera tracking of their location and bearing).
+ *
* @param enabled True to enable; false to disable.
*/
- public final void setMyLocationEnabled (boolean enabled) {
+ public final void setMyLocationEnabled(boolean enabled) {
mIsMyLocationEnabled = enabled;
toggleGps(enabled);
}
/**
* Returns the currently displayed user location, or null if there is no location data available.
+ *
* @return The currently displayed user location.
*/
- public final Location getMyLocation () {
+ public final Location getMyLocation() {
return mGpsLocation;
}
/**
* Enabled / Disable GPS location updates along with updating the UI
+ *
* @param enableGps true if GPS is to be enabled, false if GPS is to be disabled
*/
private void toggleGps(boolean enableGps) {
@@ -1945,10 +2158,68 @@ public class MapView extends FrameLayout implements LocationListener {
}
/**
+ * LOST's LocationListener Callback
+ *
+ * @param location New Location
+ */
+ @Override
+ public void onLocationChanged(Location location) {
+ updateLocation(location);
+ }
+
+ // Handles location updates from GPS
+ private void updateLocation(Location location) {
+ if (location != null) {
+ mGpsLocation = location;
+ updateGpsMarker();
+ }
+ }
+
+ private void updateGpsMarker() {
+ if (isMyLocationEnabled() && mGpsLocation != null) {
+ mGpsMarker.setVisibility(View.VISIBLE);
+ LatLng coordinate = new LatLng(mGpsLocation);
+ PointF screenLocation = toScreenLocation(coordinate);
+
+ float iconSize = 27.0f * mScreenDensity;
+ // Update Location
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) iconSize, (int) iconSize);
+ lp.leftMargin = (int) (screenLocation.x - iconSize / 2.0f);
+ lp.topMargin = getHeight() - (int) (screenLocation.y + iconSize / 2.0f);
+ mGpsMarker.setLayoutParams(lp);
+ rotateImageView(mGpsMarker, 0.0f);
+ mGpsMarker.requestLayout();
+/*
+ // Used For User Location Bearing UI
+ if (mGpsLocation.hasBearing() || mCompassValid) {
+ mGpsMarker.setImageResource(R.drawable.direction_arrow);
+ float iconSize = 54.0f * mScreenDensity;
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) iconSize, (int) iconSize);
+ lp.leftMargin = (int) (screenLocation.x - iconSize / 2.0f);
+ lp.topMargin = mMapFrameLayout.getHeight() - (int) (screenLocation.y + iconSize / 2.0f);
+ mGpsMarker.setLayoutParams(lp);
+ float bearing = mGpsLocation.hasBearing() ? mGpsLocation.getBearing() : mCompassBearing;
+ rotateImageView(mGpsMarker, bearing);
+ mGpsMarker.requestLayout();
+ }
+*/
+ } else {
+ if (mGpsMarker != null) {
+ mGpsMarker.setVisibility(View.INVISIBLE);
+ }
+ }
+ }
+
+ //
+ // Compass
+ //
+
+ /**
* Gets whether the compass is enabled/disabled.
+ *
* @return true if the compass is enabled; false if the compass is disabled.
*/
- public boolean isCompassEnabled () {
+ public boolean isCompassEnabled() {
return mIsCompassEnabled;
}
@@ -1958,57 +2229,24 @@ public class MapView extends FrameLayout implements LocationListener {
* rotated away from its default orientation (tilt of 0 and a bearing of 0). When a user clicks
* the compass, the camera orients itself to its default orientation and fades away shortly
* after. If disabled, the compass will never be displayed.
- *
+ * <p/>
* By default, the compass is enabled
+ *
* @param compassEnabled true to enable the compass; false to disable the compass.
*/
- public void setCompassEnabled (boolean compassEnabled) {
+ public void setCompassEnabled(boolean compassEnabled) {
this.mIsCompassEnabled = compassEnabled;
onInvalidate();
}
- public void setCompassGravity(int gravity){
+ public void setCompassGravity(int gravity) {
setWidgetGravity(mCompassView, gravity);
}
- public void setCompassMargins(int left, int top, int right, int bottom){
+ public void setCompassMargins(int left, int top, int right, int bottom) {
setWidgetMargins(mCompassView, left, top, right, bottom);
}
- public void setLogoGravity(int gravity){
- setWidgetGravity(mLogoView, gravity);
- }
-
- public void setLogoMargins(int left, int top, int right, int bottom){
- setWidgetMargins(mLogoView, left, top, right, bottom);
- }
-
- public void setAttributionGravity(int gravity){
- setWidgetGravity(mAttributionsView, gravity);
- }
-
- public void setAttributionMargins(int left, int top, int right, int bottom) {
- setWidgetMargins(mAttributionsView, left, top, right, bottom);
- }
-
- 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();
- layoutParams.setMargins(left,top,right,bottom);
- view.setLayoutParams(layoutParams);
- }
-
- private void setWidgetMargins(@NonNull final View view, float leftDp, float topDp, float rightDp, float bottomDp){
- LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
- layoutParams.setMargins((int)(leftDp*mScreenDensity),(int)(topDp*mScreenDensity),(int)(rightDp*mScreenDensity),(int)(bottomDp*mScreenDensity));
- view.setLayoutParams(layoutParams);
- }
-
// This class handles sensor updates to calculate compass bearing
private class CompassListener implements SensorEventListener {
@@ -2063,57 +2301,6 @@ public class MapView extends FrameLayout implements LocationListener {
}
- private static class AttributionOnClickListener implements View.OnClickListener, DialogInterface.OnClickListener {
-
- private MapView mMapView;
-
- public AttributionOnClickListener(MapView mapView) {
- mMapView = mapView;
- }
-
- // Called when someone presses the attribution icon
- @Override
- public void onClick(View v) {
- Context context = v.getContext();
- String[] items = context.getResources().getStringArray(R.array.attribution_names);
- AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AttributionAlertDialogStyle);
- builder.setTitle(R.string.attributionsDialogTitle);
- builder.setAdapter(new ArrayAdapter<>(context, R.layout.attribution_list_item, items), this);
- builder.show();
- }
-
- // Called when someone selects an attribution, 'Improve this map' adds location data to the url
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Context context = ((Dialog) dialog).getContext();
- String url = context.getResources().getStringArray(R.array.attribution_links)[which];
- if (which == ATTRIBUTION_INDEX_IMPROVE_THIS_MAP) {
- LatLng latLng = mMapView.getCenterCoordinate();
- url = String.format(url, latLng.getLongitude(), latLng.getLatitude(), (int) mMapView.getZoomLevel());
- }
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(url));
- context.startActivity(intent);
- }
- }
-
- /**
- * LOST's LocationListener Callback
- * @param location New Location
- */
- @Override
- public void onLocationChanged(Location location) {
- updateLocation(location);
- }
-
- // Handles location updates from GPS
- private void updateLocation(Location location) {
- if (location != null) {
- mGpsLocation = location;
- updateGpsMarker();
- }
- }
-
// Rotates an ImageView - does not work if the ImageView has padding, use margins
private void rotateImageView(ImageView imageView, float angle) {
Matrix matrix = new Matrix();
@@ -2133,87 +2320,79 @@ public class MapView extends FrameLayout implements LocationListener {
}
}
- private void updateGpsMarker() {
- if (isMyLocationEnabled() && mGpsLocation != null) {
- mGpsMarker.setVisibility(View.VISIBLE);
- LatLng coordinate = new LatLng(mGpsLocation);
- PointF screenLocation = toScreenLocation(coordinate);
+ //
+ // Logo
+ //
- float iconSize = 27.0f * mScreenDensity;
- // Update Location
- FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) iconSize, (int) iconSize);
- lp.leftMargin = (int) (screenLocation.x - iconSize / 2.0f);
- lp.topMargin = getHeight() - (int) (screenLocation.y + iconSize / 2.0f);
- mGpsMarker.setLayoutParams(lp);
- rotateImageView(mGpsMarker, 0.0f);
- mGpsMarker.requestLayout();
-/*
- // Used For User Location Bearing UI
- if (mGpsLocation.hasBearing() || mCompassValid) {
- mGpsMarker.setImageResource(R.drawable.direction_arrow);
- float iconSize = 54.0f * mScreenDensity;
- FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) iconSize, (int) iconSize);
- lp.leftMargin = (int) (screenLocation.x - iconSize / 2.0f);
- lp.topMargin = mMapFrameLayout.getHeight() - (int) (screenLocation.y + iconSize / 2.0f);
- mGpsMarker.setLayoutParams(lp);
- float bearing = mGpsLocation.hasBearing() ? mGpsLocation.getBearing() : mCompassBearing;
- rotateImageView(mGpsMarker, bearing);
- mGpsMarker.requestLayout();
- }
-*/
- } else {
- if (mGpsMarker != null) {
- mGpsMarker.setVisibility(View.INVISIBLE);
- }
- }
+ public void setLogoGravity(int gravity) {
+ setWidgetGravity(mLogoView, gravity);
}
- // Old tracking code
- // Update direction if tracking mode
- /*if(mUserLocationTrackingMode == UserLocationTrackingMode.FOLLOW_BEARING && mCompassValid){
- // TODO need to do proper filtering (see branch filter-compass) or else map will lock up because of all the compass events
- long t = new Date().getTime();
- if((t-t0)>1000){
- t0 = t;
- setDirection(-mCompassBearing, true);
- }
- }*/
+ public void setLogoMargins(int left, int top, int right, int bottom) {
+ setWidgetMargins(mLogoView, left, top, right, bottom);
+ }
-/*
- // TODO - Too much overhead on main thread. Needs to be refactored before it
- // can be re-enabled
- // Update map position if NOT in NONE mode
- if (mUserLocationTrackingMode != UserLocationTrackingMode.NONE) {
- setCenterCoordinate(new LatLng(mGpsLocation));
- }
-*/
+ public void setAttributionGravity(int gravity) {
+ setWidgetGravity(mAttributionsView, gravity);
+ }
- private void selectAnnotation(Annotation annotation) {
+ public void setAttributionMargins(int left, int top, int right, int bottom) {
+ setWidgetMargins(mAttributionsView, left, top, right, bottom);
+ }
- if (annotation == null) {
- return;
- }
+ private void setWidgetGravity(@NonNull final View view, int gravity) {
+ LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
+ layoutParams.gravity = gravity;
+ view.setLayoutParams(layoutParams);
+ }
- if (annotation == mSelectedAnnotation) {
- return;
- }
+ private void setWidgetMargins(@NonNull final View view, int left, int top, int right, int bottom) {
+ LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
+ layoutParams.setMargins(left, top, right, bottom);
+ view.setLayoutParams(layoutParams);
+ }
- if (annotation instanceof Marker) {
- // Need to deselect any currently selected annotation first
- deselectAnnotation();
+ private void setWidgetMargins(@NonNull final View view, float leftDp, float topDp, float rightDp, float bottomDp) {
+ LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
+ layoutParams.setMargins((int) (leftDp * mScreenDensity), (int) (topDp * mScreenDensity), (int) (rightDp * mScreenDensity), (int) (bottomDp * mScreenDensity));
+ view.setLayoutParams(layoutParams);
+ }
- ((Marker)annotation).showInfoWindow();
- mSelectedAnnotation = annotation;
+ //
+ // Attribution
+ //
+
+ private static class AttributionOnClickListener implements View.OnClickListener, DialogInterface.OnClickListener {
+
+ private MapView mMapView;
+
+ public AttributionOnClickListener(MapView mapView) {
+ mMapView = mapView;
}
- }
- private void deselectAnnotation() {
- if (mSelectedAnnotation != null && mSelectedAnnotation instanceof Marker) {
- Marker marker = (Marker) mSelectedAnnotation;
- if (marker.isInfoWindowShown()) {
- marker.hideInfoWindow();
- mSelectedAnnotation = null;
+ // Called when someone presses the attribution icon
+ @Override
+ public void onClick(View v) {
+ Context context = v.getContext();
+ String[] items = context.getResources().getStringArray(R.array.attribution_names);
+ AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AttributionAlertDialogStyle);
+ builder.setTitle(R.string.attributionsDialogTitle);
+ builder.setAdapter(new ArrayAdapter<>(context, R.layout.attribution_list_item, items), this);
+ builder.show();
+ }
+
+ // Called when someone selects an attribution, 'Improve this map' adds location data to the url
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Context context = ((Dialog) dialog).getContext();
+ String url = context.getResources().getStringArray(R.array.attribution_links)[which];
+ if (which == ATTRIBUTION_INDEX_IMPROVE_THIS_MAP) {
+ LatLng latLng = mMapView.getCenterCoordinate();
+ url = String.format(url, latLng.getLongitude(), latLng.getLatitude(), (int) mMapView.getZoomLevel());
}
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ context.startActivity(intent);
}
}
}
diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/package-info.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/package-info.java
new file mode 100644
index 0000000000..33710dca77
--- /dev/null
+++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Classes that render a map and the map's UI.
+ */
+package com.mapbox.mapboxgl.views;
diff --git a/android/java/MapboxGLAndroidSDK/src/main/res/layout/infowindow.xml b/android/java/MapboxGLAndroidSDK/src/main/res/layout/infowindow.xml
index af05e2fd40..7f042363ce 100644
--- a/android/java/MapboxGLAndroidSDK/src/main/res/layout/infowindow.xml
+++ b/android/java/MapboxGLAndroidSDK/src/main/res/layout/infowindow.xml
@@ -44,7 +44,7 @@
android:visibility="gone"/>
</LinearLayout>
- <com.mapbox.mapboxgl.annotations.InfoWindowTipView
+ <com.mapbox.mapboxgl.views.InfoWindowTipView
android:layout_width="fill_parent"
android:layout_height="10dp"/>
diff --git a/android/java/MapboxGLAndroidSDK/src/main/res/values/arrays.xml b/android/java/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
index 8a8e204b7d..2c1fdf8d13 100644
--- a/android/java/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
+++ b/android/java/MapboxGLAndroidSDK/src/main/res/values/arrays.xml
@@ -5,6 +5,7 @@
<item>&#169; OpenStreetMap</item>
<item>Improve this map</item>
</array>
+ <!-- If editing this array update MapView.ATTRIBUTION_INDEX_IMPROVE_THIS_MAP -->
<array name="attribution_links" formatted="false" translatable="false">
<item>https://www.mapbox.com/about/maps/</item>
<item>http://www.openstreetmap.org/about/</item>