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.java538
1 files changed, 319 insertions, 219 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 19cad1d8e0..256f49ef52 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,13 +1,10 @@
package com.mapbox.mapboxsdk.maps;
-import android.app.Activity;
-import android.app.Fragment;
import android.content.Context;
-import android.graphics.Canvas;
import android.graphics.PointF;
-import android.graphics.SurfaceTexture;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.support.annotation.CallSuper;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
@@ -18,33 +15,40 @@ 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.Mapbox;
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.maps.renderer.MapRenderer;
+import com.mapbox.mapboxsdk.maps.renderer.glsurfaceview.GLSurfaceViewMapRenderer;
+import com.mapbox.mapboxsdk.maps.renderer.textureview.TextureViewMapRenderer;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
+import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.services.android.telemetry.MapboxTelemetry;
+import timber.log.Timber;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_MAP_NORTH_ANIMATION;
+import static com.mapbox.mapboxsdk.maps.widgets.CompassView.TIME_WAIT_IDLE;
/**
* <p>
@@ -62,17 +66,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 MapRenderer mapRenderer;
@UiThread
public MapView(@NonNull Context context) {
@@ -100,28 +113,42 @@ public class MapView extends FrameLayout {
private void initialise(@NonNull final Context context, @NonNull final MapboxMapOptions options) {
if (isInEditMode()) {
- // in IDE, show preview map
- LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_preview, this);
+ // 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);
- // create native Map object
- nativeMapView = new NativeMapView(this);
+ 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(options);
+ }
+ });
+ }
+
+ 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();
@@ -130,13 +157,15 @@ 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));
IconManager iconManager = new IconManager(nativeMapView);
@@ -144,23 +173,32 @@ public class MapView extends FrameLayout {
Markers markers = new MarkerContainer(nativeMapView, this, annotationsArray, iconManager, markerViewManager);
Polygons polygons = new PolygonContainer(nativeMapView, annotationsArray);
Polylines polylines = new PolylineContainer(nativeMapView, annotationsArray);
+ ShapeAnnotations shapeAnnotations = new ShapeAnnotationContainer(nativeMapView, annotationsArray);
AnnotationManager annotationManager = new AnnotationManager(nativeMapView, this, annotationsArray,
- markerViewManager, iconManager, annotations, markers, polygons, polylines);
+ markerViewManager, iconManager, annotations, markers, polygons, polylines, shapeAnnotations);
Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings,
cameraChangeDispatcher);
+
mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, proj,
registerTouchListener, annotationManager, cameraChangeDispatcher);
+ focalPointInvalidator.addListener(mapboxMap.createFocalPointChangeListener());
+
+ mapCallback.attachMapboxMap(mapboxMap);
// user input
mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings,
annotationManager, cameraChangeDispatcher);
mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings);
- MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform);
- mapZoomButtonController = new MapZoomButtonController(this, uiSettings, zoomListener);
+ // overlain zoom buttons
+ mapZoomButtonController = new MapZoomButtonController(new ZoomButtonsController(this));
+ MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform,
+ cameraChangeDispatcher, getWidth(), getHeight());
+ 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));
@@ -171,14 +209,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);
+ }
+ }
+ };
}
//
@@ -187,103 +269,160 @@ public class MapView extends FrameLayout {
/**
* <p>
- * You must call this method from the parent's {@link android.app.Activity#onCreate(Bundle)} or
- * {@link android.app.Fragment#onCreate(Bundle)}.
+ * You must call this method from the parent's Activity#onCreate(Bundle)} or
+ * Fragment#onViewCreated(View, Bundle).
* </p>
- * You must set a valid access token with {@link Mapbox#getInstance(Context, String)}) before you call this method
- * or an exception will be thrown.
+ * You must set a valid access token with {@link com.mapbox.mapboxsdk.Mapbox#getInstance(Context, String)}
+ * before you call this method or an exception will be thrown.
*
* @param savedInstanceState Pass in the parent's savedInstanceState.
- * @see Mapbox#getInstance(Context, String)
+ * @see com.mapbox.mapboxsdk.Mapbox#getInstance(Context, String)
*/
@UiThread
public void onCreate(@Nullable Bundle savedInstanceState) {
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) {
+ private void initialiseDrawingSurface(MapboxMapOptions options) {
+ if (options.getTextureMode()) {
TextureView textureView = new TextureView(getContext());
- textureView.setSurfaceTextureListener(new SurfaceTextureListener());
+ mapRenderer = new TextureViewMapRenderer(getContext(), textureView, options.getLocalIdeographFontFamily()) {
+ @Override
+ protected void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ initRenderSurface();
+ super.onSurfaceCreated(gl, config);
+ }
+ };
+
addView(textureView, 0);
} else {
- SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
- surfaceView.getHolder().addCallback(new SurfaceCallback());
- surfaceView.setVisibility(View.VISIBLE);
+ GLSurfaceView glSurfaceView = (GLSurfaceView) findViewById(R.id.surfaceView);
+ glSurfaceView.setZOrderMediaOverlay(mapboxMapOptions.getRenderSurfaceOnTop());
+ mapRenderer = new GLSurfaceViewMapRenderer(getContext(), glSurfaceView, options.getLocalIdeographFontFamily()) {
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ initRenderSurface();
+ super.onSurfaceCreated(gl, config);
+ }
+ };
+
+ glSurfaceView.setVisibility(View.VISIBLE);
}
+
+ nativeMapView = new NativeMapView(this, mapRenderer);
+ nativeMapView.resizeView(getMeasuredWidth(), getMeasuredHeight());
+ }
+
+ private void initRenderSurface() {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ // Initialise only when not destroyed and only once
+ if (!destroyed && mapboxMap == null) {
+ initialiseMap();
+ mapboxMap.onStart();
+ }
+ }
+ });
}
/**
- * You must call this method from the parent's {@link android.app.Activity#onSaveInstanceState(Bundle)}
- * or {@link android.app.Fragment#onSaveInstanceState(Bundle)}.
+ * You must call this method from the parent's Activity#onSaveInstanceState(Bundle)
+ * or Fragment#onSaveInstanceState(Bundle).
*
* @param outState Pass in the parent's outState.
*/
-
@UiThread
public void onSaveInstanceState(@NonNull Bundle outState) {
- outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true);
- mapboxMap.onSaveInstanceState(outState);
+ if (mapboxMap != null) {
+ outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true);
+ mapboxMap.onSaveInstanceState(outState);
+ }
}
/**
- * You must call this method from the parent's {@link Activity#onStart()} or {@link Fragment#onStart()}
+ * You must call this method from the parent's Activity#onStart() or Fragment#onStart()
*/
@UiThread
public void onStart() {
- mapboxMap.onStart();
ConnectivityReceiver.instance(getContext()).activate();
+ FileSource.getInstance(getContext()).activate();
+ if (mapboxMap != null) {
+ mapboxMap.onStart();
+ }
+
+ if (mapRenderer != null) {
+ mapRenderer.onStart();
+ }
}
/**
- * You must call this method from the parent's {@link Activity#onResume()} or {@link Fragment#onResume()}.
+ * You must call this method from the parent's Activity#onResume() or Fragment#onResume().
*/
@UiThread
public void onResume() {
- // replaced by onStart in v5.0.0
+ if (mapRenderer != null) {
+ mapRenderer.onResume();
+ }
}
/**
- * You must call this method from the parent's {@link Activity#onPause()} or {@link Fragment#onPause()}.
+ * You must call this method from the parent's Activity#onPause() or Fragment#onPause().
*/
@UiThread
public void onPause() {
- // replaced by onStop in v5.0.0
+ if (mapRenderer != null) {
+ mapRenderer.onPause();
+ }
}
/**
- * You must call this method from the parent's {@link Activity#onStop()} or {@link Fragment#onStop()}.
+ * You must call this method from the parent's Activity#onStop() or Fragment#onStop().
*/
@UiThread
public void onStop() {
- mapboxMap.onStop();
+ if (mapboxMap != null) {
+ // map was destroyed before it was started
+ mapboxMap.onStop();
+ }
+
+ if (mapRenderer != null) {
+ mapRenderer.onStop();
+ }
+
ConnectivityReceiver.instance(getContext()).deactivate();
+ FileSource.getInstance(getContext()).deactivate();
}
/**
- * You must call this method from the parent's {@link Activity#onDestroy()} or {@link Fragment#onDestroy()}.
+ * You must call this method from the parent's Activity#onDestroy() or Fragment#onDestroyView().
*/
@UiThread
public void onDestroy() {
destroyed = true;
- nativeMapView.terminateContext();
- nativeMapView.terminateDisplay();
- nativeMapView.destroySurface();
- nativeMapView.destroy();
- nativeMapView = null;
+ mapCallback.clearOnMapReadyCallbacks();
+
+ if (nativeMapView != null) {
+ // null when destroying an activity programmatically mapbox-navigation-android/issues/503
+ nativeMapView.destroy();
+ nativeMapView = null;
+ }
+
+ if (mapRenderer != null) {
+ mapRenderer.onDestroy();
+ }
}
@Override
public boolean onTouchEvent(MotionEvent event) {
+ if (!isMapInitialized() || !isZoomButtonControllerInitialized()) {
+ return super.onTouchEvent(event);
+ }
+
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mapZoomButtonController.setVisible(true);
}
@@ -312,11 +451,18 @@ public class MapView extends FrameLayout {
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
+ if (mapGestureDetector == null) {
+ return super.onGenericMotionEvent(event);
+ }
return mapGestureDetector.onGenericMotionEvent(event) || super.onGenericMotionEvent(event);
}
@Override
public boolean onHoverEvent(MotionEvent event) {
+ if (!isZoomButtonControllerInitialized()) {
+ return super.onHoverEvent(event);
+ }
+
switch (event.getActionMasked()) {
case MotionEvent.ACTION_HOVER_ENTER:
case MotionEvent.ACTION_HOVER_MOVE:
@@ -334,28 +480,13 @@ public class MapView extends FrameLayout {
}
/**
- * You must call this method from the parent's {@link Activity#onLowMemory()} or {@link Fragment#onLowMemory()}.
+ * You must call this method from the parent's Activity#onLowMemory() or Fragment#onLowMemory().
*/
@UiThread
public void onLowMemory() {
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.
@@ -388,7 +519,10 @@ public class MapView extends FrameLayout {
if (destroyed) {
return;
}
-
+ if (!isMapInitialized()) {
+ mapboxMapOptions.styleUrl(url);
+ return;
+ }
nativeMapView.setStyleUrl(url);
}
@@ -396,119 +530,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() && isMapInitialized()) {
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
//
@@ -518,7 +550,7 @@ public class MapView extends FrameLayout {
@CallSuper
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- if (mapZoomButtonController != null) {
+ if (isZoomButtonControllerInitialized()) {
mapZoomButtonController.setVisible(false);
}
}
@@ -526,16 +558,29 @@ public class MapView extends FrameLayout {
// 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 (isZoomButtonControllerInitialized()) {
+ 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>
* Add a callback that's invoked when the displayed map view changes.
@@ -547,7 +592,7 @@ public class MapView extends FrameLayout {
*/
public void addOnMapChangedListener(@Nullable OnMapChangedListener listener) {
if (listener != null) {
- nativeMapView.addOnMapChangedListener(listener);
+ onMapChangedListeners.add(listener);
}
}
@@ -559,7 +604,7 @@ public class MapView extends FrameLayout {
*/
public void removeOnMapChangedListener(@Nullable OnMapChangedListener listener) {
if (listener != null) {
- nativeMapView.removeOnMapChangedListener(listener);
+ onMapChangedListeners.remove(listener);
}
}
@@ -579,6 +624,14 @@ public class MapView extends FrameLayout {
}
}
+ private boolean isMapInitialized() {
+ return nativeMapView != null;
+ }
+
+ private boolean isZoomButtonControllerInitialized() {
+ return mapZoomButtonController != null;
+ }
+
MapboxMap getMapboxMap() {
return mapboxMap;
}
@@ -783,7 +836,7 @@ public class MapView extends FrameLayout {
public static final int DID_FINISH_LOADING_STYLE = 14;
/**
- * This {@link MapChange} is triggered when a source attribution changes.
+ * This {@link MapChange} is triggered when a source changes.
* <p>
* Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}.
* </p>
@@ -826,10 +879,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
@@ -844,36 +897,83 @@ public class MapView extends FrameLayout {
private class RegisterTouchListener implements MapboxMap.OnRegisterTouchListener {
@Override
- public void onRegisterMapClickListener(MapboxMap.OnMapClickListener listener) {
+ public void onSetMapClickListener(MapboxMap.OnMapClickListener listener) {
mapGestureDetector.setOnMapClickListener(listener);
}
@Override
- public void onRegisterMapLongClickListener(MapboxMap.OnMapLongClickListener listener) {
+ public void onAddMapClickListener(MapboxMap.OnMapClickListener listener) {
+ mapGestureDetector.addOnMapClickListener(listener);
+ }
+
+ @Override
+ public void onRemoveMapClickListener(MapboxMap.OnMapClickListener listener) {
+ mapGestureDetector.removeOnMapClickListener(listener);
+ }
+
+ @Override
+ public void onSetMapLongClickListener(MapboxMap.OnMapLongClickListener listener) {
mapGestureDetector.setOnMapLongClickListener(listener);
}
@Override
- public void onRegisterScrollListener(MapboxMap.OnScrollListener listener) {
+ public void onAddMapLongClickListener(MapboxMap.OnMapLongClickListener listener) {
+ mapGestureDetector.addOnMapLongClickListener(listener);
+ }
+
+ @Override
+ public void onRemoveMapLongClickListener(MapboxMap.OnMapLongClickListener listener) {
+ mapGestureDetector.removeOnMapLongClickListener(listener);
+ }
+
+ @Override
+ public void onSetScrollListener(MapboxMap.OnScrollListener listener) {
mapGestureDetector.setOnScrollListener(listener);
}
@Override
- public void onRegisterFlingListener(MapboxMap.OnFlingListener listener) {
+ public void onAddScrollListener(MapboxMap.OnScrollListener listener) {
+ mapGestureDetector.addOnScrollListener(listener);
+ }
+
+ @Override
+ public void onRemoveScrollListener(MapboxMap.OnScrollListener listener) {
+ mapGestureDetector.removeOnScrollListener(listener);
+ }
+
+ @Override
+ public void onSetFlingListener(MapboxMap.OnFlingListener listener) {
mapGestureDetector.setOnFlingListener(listener);
}
+
+ @Override
+ public void onAddFlingListener(MapboxMap.OnFlingListener listener) {
+ mapGestureDetector.addOnFlingListener(listener);
+ }
+
+ @Override
+ public void onRemoveFlingListener(MapboxMap.OnFlingListener listener) {
+ mapGestureDetector.removeOnFlingListener(listener);
+ }
}
- private class MapZoomControllerListener implements ZoomButtonsController.OnZoomListener {
+ private static class MapZoomControllerListener implements ZoomButtonsController.OnZoomListener {
private final MapGestureDetector mapGestureDetector;
private final UiSettings uiSettings;
private final Transform transform;
+ private final CameraChangeDispatcher cameraChangeDispatcher;
+ private final float mapWidth;
+ private final float mapHeight;
- MapZoomControllerListener(MapGestureDetector detector, UiSettings uiSettings, Transform transform) {
+ MapZoomControllerListener(MapGestureDetector detector, UiSettings uiSettings, Transform transform,
+ CameraChangeDispatcher dispatcher, float mapWidth, float mapHeight) {
this.mapGestureDetector = detector;
this.uiSettings = uiSettings;
this.transform = transform;
+ this.cameraChangeDispatcher = dispatcher;
+ this.mapWidth = mapWidth;
+ this.mapHeight = mapHeight;
}
// Not used
@@ -886,6 +986,7 @@ public class MapView extends FrameLayout {
@Override
public void onZoom(boolean zoomIn) {
if (uiSettings.isZoomGesturesEnabled()) {
+ cameraChangeDispatcher.onCameraMoveStarted(CameraChangeDispatcher.REASON_API_ANIMATION);
onZoom(zoomIn, mapGestureDetector.getFocalPoint());
}
}
@@ -894,7 +995,7 @@ public class MapView extends FrameLayout {
if (focalPoint != null) {
transform.zoom(zoomIn, focalPoint);
} else {
- PointF centerPoint = new PointF(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
+ PointF centerPoint = new PointF(mapWidth / 2, mapHeight / 2);
transform.zoom(zoomIn, centerPoint);
}
}
@@ -923,11 +1024,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;
}
@@ -935,14 +1036,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) {
@@ -969,5 +1065,9 @@ public class MapView extends FrameLayout {
void addOnMapReadyCallback(OnMapReadyCallback callback) {
onMapReadyCallbackList.add(callback);
}
+
+ void clearOnMapReadyCallbacks() {
+ onMapReadyCallbackList.clear();
+ }
}
}