summaryrefslogtreecommitdiff
path: root/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java')
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java397
1 files changed, 200 insertions, 197 deletions
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 9fa3126523..12e4c675ee 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,34 +1,34 @@
package com.mapbox.mapboxsdk.maps;
import android.content.Context;
-import android.graphics.Canvas;
import android.graphics.PointF;
-import android.graphics.SurfaceTexture;
+import android.os.Build;
+import android.opengl.GLSurfaceView;
import android.os.Bundle;
-import android.os.Handler;
import android.support.annotation.CallSuper;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
+import android.support.v4.util.LongSparseArray;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ZoomButtonsController;
import com.mapbox.mapboxsdk.R;
+import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.Style;
+import com.mapbox.mapboxsdk.egl.EGLConfigChooser;
+import com.mapbox.mapboxsdk.maps.renderer.MapRenderer;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
@@ -40,6 +40,16 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
+import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_WAIT_IDLE;
+import static android.opengl.GLSurfaceView.RENDERMODE_WHEN_DIRTY;
/**
* <p>
@@ -57,17 +67,26 @@ import java.util.List;
*/
public class MapView extends FrameLayout {
+ private final MapCallback mapCallback = new MapCallback();
+ private MapboxMap mapboxMap;
+
private NativeMapView nativeMapView;
- private boolean textureMode;
+ private MapboxMapOptions mapboxMapOptions;
private boolean destroyed;
- private boolean hasSurface;
- private MapboxMap mapboxMap;
- private MapCallback mapCallback;
+ private MyLocationView myLocationView;
+ private CompassView compassView;
+ private PointF focalPoint;
+ private ImageView attrView;
+ private ImageView logoView;
private MapGestureDetector mapGestureDetector;
private MapKeyListener mapKeyListener;
private MapZoomButtonController mapZoomButtonController;
+ private Bundle savedInstanceState;
+ private final CopyOnWriteArrayList<OnMapChangedListener> onMapChangedListeners = new CopyOnWriteArrayList<>();
+
+ private GLSurfaceView glSurfaceView;
@UiThread
public MapView(@NonNull Context context) {
@@ -98,24 +117,39 @@ public class MapView extends FrameLayout {
// in IDE layout editor, just return
return;
}
-
- // determine render surface
- textureMode = options.getTextureMode();
+ mapboxMapOptions = options;
// inflate view
View view = LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this);
- CompassView compassView = (CompassView) view.findViewById(R.id.compassView);
- MyLocationView myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView);
- ImageView attrView = (ImageView) view.findViewById(R.id.attributionView);
+ compassView = (CompassView) view.findViewById(R.id.compassView);
+ myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView);
+ attrView = (ImageView) view.findViewById(R.id.attributionView);
+ logoView = (ImageView) view.findViewById(R.id.logoView);
// add accessibility support
setContentDescription(context.getString(R.string.mapbox_mapActionDescription));
+ setWillNotDraw(false);
+
+ getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ } else {
+ getViewTreeObserver().removeGlobalOnLayoutListener(this);
+ }
+ initialiseDrawingSurface();
+ }
+ });
+ }
- // create native Map object
- nativeMapView = new NativeMapView(this);
+ private void initialiseMap() {
+ Context context = getContext();
+ addOnMapChangedListener(mapCallback);
// callback for focal point invalidation
- FocalPointInvalidator focalPoint = new FocalPointInvalidator(compassView);
+ final FocalPointInvalidator focalPointInvalidator = new FocalPointInvalidator();
+ focalPointInvalidator.addListener(createFocalPointChangeListener());
// callback for registering touch listeners
RegisterTouchListener registerTouchListener = new RegisterTouchListener();
@@ -124,30 +158,45 @@ public class MapView extends FrameLayout {
CameraZoomInvalidator zoomInvalidator = new CameraZoomInvalidator();
// callback for camera change events
- CameraChangeDispatcher cameraChangeDispatcher = new CameraChangeDispatcher();
+ final CameraChangeDispatcher cameraChangeDispatcher = new CameraChangeDispatcher();
// setup components for MapboxMap creation
Projection proj = new Projection(nativeMapView);
- UiSettings uiSettings = new UiSettings(proj, focalPoint, compassView, attrView, view.findViewById(R.id.logoView));
- TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPoint, zoomInvalidator);
- MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, proj, focalPoint);
+ UiSettings uiSettings = new UiSettings(proj, focalPointInvalidator, compassView, attrView, logoView);
+ TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPointInvalidator,
+ zoomInvalidator);
+ MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, proj,
+ focalPointInvalidator);
+ LongSparseArray<Annotation> annotationsArray = new LongSparseArray<>();
MarkerViewManager markerViewManager = new MarkerViewManager((ViewGroup) findViewById(R.id.markerViewContainer));
- AnnotationManager annotations = new AnnotationManager(nativeMapView, this, markerViewManager);
- Transform transform = new Transform(nativeMapView, annotations.getMarkerViewManager(), trackingSettings,
+ IconManager iconManager = new IconManager(nativeMapView);
+ Annotations annotations = new AnnotationContainer(nativeMapView, annotationsArray);
+ Markers markers = new MarkerContainer(nativeMapView, this, annotationsArray, iconManager, markerViewManager);
+ Polygons polygons = new PolygonContainer(nativeMapView, annotationsArray);
+ Polylines polylines = new PolylineContainer(nativeMapView, annotationsArray);
+ AnnotationManager annotationManager = new AnnotationManager(nativeMapView, this, annotationsArray,
+ markerViewManager, iconManager, annotations, markers, polygons, polylines);
+ Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings,
cameraChangeDispatcher);
+
mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, proj,
- registerTouchListener, annotations, cameraChangeDispatcher);
+ registerTouchListener, annotationManager, cameraChangeDispatcher);
+ focalPointInvalidator.addListener(mapboxMap.createFocalPointChangeListener());
+
+ mapCallback.attachMapboxMap(mapboxMap);
// user input
- mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings, annotations,
- cameraChangeDispatcher);
+ mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings,
+ annotationManager, cameraChangeDispatcher);
mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings);
+ mapZoomButtonController = new MapZoomButtonController(new ZoomButtonsController(this));
MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform);
- mapZoomButtonController = new MapZoomButtonController(this, uiSettings, zoomListener);
+ mapZoomButtonController.bind(uiSettings, zoomListener);
+ compassView.injectCompassAnimationListener(createCompassAnimationListener(cameraChangeDispatcher));
+ compassView.setOnClickListener(createCompassClickListener(cameraChangeDispatcher));
// inject widgets with MapboxMap
- compassView.setMapboxMap(mapboxMap);
myLocationView.setMapboxMap(mapboxMap);
attrView.setOnClickListener(new AttributionDialogManager(context, mapboxMap));
@@ -158,14 +207,58 @@ public class MapView extends FrameLayout {
setFocusableInTouchMode(true);
requestDisallowInterceptTouchEvent(true);
- // allow onDraw invocation
- setWillNotDraw(false);
-
// notify Map object about current connectivity state
nativeMapView.setReachability(ConnectivityReceiver.instance(context).isConnected(context));
// initialise MapboxMap
- mapboxMap.initialise(context, options);
+ if (savedInstanceState == null) {
+ mapboxMap.initialise(context, mapboxMapOptions);
+ } else {
+ mapboxMap.onRestoreInstanceState(savedInstanceState);
+ }
+ }
+
+ private FocalPointChangeListener createFocalPointChangeListener() {
+ return new FocalPointChangeListener() {
+ @Override
+ public void onFocalPointChanged(PointF pointF) {
+ focalPoint = pointF;
+ }
+ };
+ }
+
+ private MapboxMap.OnCompassAnimationListener createCompassAnimationListener(final CameraChangeDispatcher
+ cameraChangeDispatcher) {
+ return new MapboxMap.OnCompassAnimationListener() {
+ @Override
+ public void onCompassAnimation() {
+ cameraChangeDispatcher.onCameraMove();
+ }
+
+ @Override
+ public void onCompassAnimationFinished() {
+ compassView.isAnimating(false);
+ cameraChangeDispatcher.onCameraIdle();
+ }
+ };
+ }
+
+ private OnClickListener createCompassClickListener(final CameraChangeDispatcher cameraChangeDispatcher) {
+ return new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mapboxMap != null && compassView != null) {
+ if (focalPoint != null) {
+ mapboxMap.setFocalBearing(0, focalPoint.x, focalPoint.y, TIME_MAP_NORTH_ANIMATION);
+ } else {
+ mapboxMap.setFocalBearing(0, mapboxMap.getWidth() / 2, mapboxMap.getHeight() / 2, TIME_MAP_NORTH_ANIMATION);
+ }
+ cameraChangeDispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_ANIMATION);
+ compassView.isAnimating(true);
+ compassView.postDelayed(compassView, TIME_WAIT_IDLE + TIME_MAP_NORTH_ANIMATION);
+ }
+ }
+ };
}
//
@@ -188,25 +281,40 @@ public class MapView extends FrameLayout {
if (savedInstanceState == null) {
MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapLoadEvent());
} else if (savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) {
- mapboxMap.onRestoreInstanceState(savedInstanceState);
+ this.savedInstanceState = savedInstanceState;
}
-
- initialiseDrawingSurface(textureMode);
- addOnMapChangedListener(mapCallback = new MapCallback(mapboxMap));
}
- private void initialiseDrawingSurface(boolean textureMode) {
- nativeMapView.initializeDisplay();
- nativeMapView.initializeContext();
- if (textureMode) {
- TextureView textureView = new TextureView(getContext());
- textureView.setSurfaceTextureListener(new SurfaceTextureListener());
- addView(textureView, 0);
- } else {
- SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
- surfaceView.getHolder().addCallback(new SurfaceCallback());
- surfaceView.setVisibility(View.VISIBLE);
- }
+ private void initialiseDrawingSurface() {
+ glSurfaceView = (GLSurfaceView) findViewById(R.id.surfaceView);
+ glSurfaceView.setZOrderMediaOverlay(mapboxMapOptions.getRenderSurfaceOnTop());
+ glSurfaceView.setEGLContextClientVersion(2);
+ glSurfaceView.setEGLConfigChooser(new EGLConfigChooser());
+
+ MapRenderer mapRenderer = new MapRenderer(getContext(), glSurfaceView) {
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ MapView.this.post(new Runnable() {
+ @Override
+ public void run() {
+ // Initialise only once
+ if (mapboxMap == null) {
+ initialiseMap();
+ mapboxMap.onStart();
+ }
+ }
+ });
+
+ super.onSurfaceCreated(gl, config);
+ }
+ };
+
+ glSurfaceView.setRenderer(mapRenderer);
+ glSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY);
+ glSurfaceView.setVisibility(View.VISIBLE);
+
+ nativeMapView = new NativeMapView(this, mapRenderer);
+ nativeMapView.resizeView(getMeasuredWidth(), getMeasuredHeight());
}
/**
@@ -226,8 +334,10 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onStart() {
- mapboxMap.onStart();
ConnectivityReceiver.instance(getContext()).activate();
+ if (mapboxMap != null) {
+ mapboxMap.onStart();
+ }
}
/**
@@ -235,7 +345,9 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onResume() {
- // replaced by onStart in v5.0.0
+ if (glSurfaceView != null) {
+ glSurfaceView.onResume();
+ }
}
/**
@@ -243,7 +355,9 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onPause() {
- // replaced by onStop in v5.0.0
+ if (glSurfaceView != null) {
+ glSurfaceView.onPause();
+ }
}
/**
@@ -261,9 +375,6 @@ public class MapView extends FrameLayout {
@UiThread
public void onDestroy() {
destroyed = true;
- nativeMapView.terminateContext();
- nativeMapView.terminateDisplay();
- nativeMapView.destroySurface();
mapCallback.clearOnMapReadyCallbacks();
nativeMapView.destroy();
nativeMapView = null;
@@ -328,21 +439,6 @@ public class MapView extends FrameLayout {
nativeMapView.onLowMemory();
}
- // Called when debug mode is enabled to update a FPS counter
- // Called via JNI from NativeMapView
- // Forward to any listener
- protected void onFpsChanged(final double fps) {
- final MapboxMap.OnFpsChangedListener listener = mapboxMap.getOnFpsChangedListener();
- if (listener != null) {
- post(new Runnable() {
- @Override
- public void run() {
- listener.onFpsChanged(fps);
- }
- });
- }
- }
-
/**
* <p>
* Loads a new map style from the specified URL.
@@ -375,7 +471,10 @@ public class MapView extends FrameLayout {
if (destroyed) {
return;
}
-
+ if (nativeMapView == null) {
+ mapboxMapOptions.styleUrl(url);
+ return;
+ }
nativeMapView.setStyleUrl(url);
}
@@ -383,119 +482,17 @@ public class MapView extends FrameLayout {
// Rendering
//
- // Called when the map needs to be rerendered
- // Called via JNI from NativeMapView
- protected void onInvalidate() {
- postInvalidate();
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (isInEditMode()) {
- return;
- }
-
- if (destroyed) {
- return;
- }
-
- if (!hasSurface) {
- return;
- }
-
- nativeMapView.render();
- }
-
@Override
protected void onSizeChanged(int width, int height, int oldw, int oldh) {
if (destroyed) {
return;
}
- if (!isInEditMode()) {
+ if (!isInEditMode() && nativeMapView != null) {
nativeMapView.resizeView(width, height);
}
}
- private class SurfaceCallback implements SurfaceHolder.Callback {
-
- private Surface surface;
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- nativeMapView.createSurface(surface = holder.getSurface());
- hasSurface = true;
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- if (destroyed) {
- return;
- }
- nativeMapView.resizeFramebuffer(width, height);
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- hasSurface = false;
-
- if (nativeMapView != null) {
- nativeMapView.destroySurface();
- }
- surface.release();
- }
- }
-
- // This class handles TextureView callbacks
- private class SurfaceTextureListener implements TextureView.SurfaceTextureListener {
-
- private Surface surface;
-
- // 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) {
- nativeMapView.createSurface(this.surface = new Surface(surface));
- nativeMapView.resizeFramebuffer(width, height);
- hasSurface = true;
- }
-
- // Called when the native surface texture has been destroyed
- // Must do all EGL/GL ES destruction here
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- hasSurface = false;
-
- if (nativeMapView != null) {
- nativeMapView.destroySurface();
- }
- this.surface.release();
- return true;
- }
-
- // 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) {
- if (destroyed) {
- return;
- }
-
- nativeMapView.resizeFramebuffer(width, height);
- }
-
- // Called when the SurfaceTexure frame is drawn to screen
- // Must sync with UI here
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- if (destroyed) {
- return;
- }
- mapboxMap.onUpdateRegionChange();
- }
- }
-
//
// View events
//
@@ -505,26 +502,37 @@ public class MapView extends FrameLayout {
@CallSuper
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- if (mapZoomButtonController != null) {
- mapZoomButtonController.setVisible(false);
- }
+ mapZoomButtonController.setVisible(false);
}
// Called when view is hidden and shown
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
- if (isInEditMode() || mapZoomButtonController == null) {
+ if (isInEditMode()) {
return;
}
- mapZoomButtonController.setVisible(visibility == View.VISIBLE);
+
+ if (mapZoomButtonController != null) {
+ mapZoomButtonController.setVisible(visibility == View.VISIBLE);
+ }
}
//
// Map events
//
+ void onMapChange(int rawChange) {
+ for (MapView.OnMapChangedListener onMapChangedListener : onMapChangedListeners) {
+ try {
+ onMapChangedListener.onMapChanged(rawChange);
+ } catch (RuntimeException err) {
+ Timber.e(err, "Exception in MapView.OnMapChangedListener");
+ }
+ }
+ }
+
/**
- * <p>P
+ * <p>
* Add a callback that's invoked when the displayed map view changes.
* </p>
* To remove the callback, use {@link MapView#removeOnMapChangedListener(OnMapChangedListener)}.
@@ -534,7 +542,7 @@ public class MapView extends FrameLayout {
*/
public void addOnMapChangedListener(@Nullable OnMapChangedListener listener) {
if (listener != null) {
- nativeMapView.addOnMapChangedListener(listener);
+ onMapChangedListeners.add(listener);
}
}
@@ -546,7 +554,7 @@ public class MapView extends FrameLayout {
*/
public void removeOnMapChangedListener(@Nullable OnMapChangedListener listener) {
if (listener != null) {
- nativeMapView.removeOnMapChangedListener(listener);
+ onMapChangedListeners.remove(listener);
}
}
@@ -813,10 +821,10 @@ public class MapView extends FrameLayout {
private class FocalPointInvalidator implements FocalPointChangeListener {
- private final FocalPointChangeListener[] focalPointChangeListeners;
+ private final List<FocalPointChangeListener> focalPointChangeListeners = new ArrayList<>();
- FocalPointInvalidator(FocalPointChangeListener... listeners) {
- focalPointChangeListeners = listeners;
+ void addListener(FocalPointChangeListener focalPointChangeListener) {
+ focalPointChangeListeners.add(focalPointChangeListener);
}
@Override
@@ -910,11 +918,11 @@ public class MapView extends FrameLayout {
private static class MapCallback implements OnMapChangedListener {
- private final MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
private final List<OnMapReadyCallback> onMapReadyCallbackList = new ArrayList<>();
private boolean initialLoad = true;
- MapCallback(MapboxMap mapboxMap) {
+ void attachMapboxMap(MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
}
@@ -922,14 +930,9 @@ public class MapView extends FrameLayout {
public void onMapChanged(@MapChange int change) {
if (change == DID_FINISH_LOADING_STYLE && initialLoad) {
initialLoad = false;
- new Handler().post(new Runnable() {
- @Override
- public void run() {
- mapboxMap.onPreMapReady();
- onMapReady();
- mapboxMap.onPostMapReady();
- }
- });
+ mapboxMap.onPreMapReady();
+ onMapReady();
+ mapboxMap.onPostMapReady();
} else if (change == DID_FINISH_RENDERING_FRAME || change == DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) {
mapboxMap.onUpdateFullyRendered();
} else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) {