diff --git a/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLManager.java b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLManager.java index 4ab09a2..f81e341 100644 --- a/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLManager.java +++ b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLManager.java @@ -1,21 +1,11 @@ package com.mapbox.reactnativemapboxgl; -import android.os.StrictMode; -import android.support.annotation.Keep; -import android.util.Log; - -import com.facebook.common.internal.DoNotStrip; -import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.annotations.ReactProp; -import com.facebook.react.uimanager.annotations.ReactPropGroup; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.SimpleViewManager; -import com.mapbox.mapboxsdk.maps.MapView; -import com.mapbox.mapboxsdk.maps.MapboxMap; -import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import javax.annotation.Nonnull; @@ -42,9 +32,43 @@ public class ReactNativeMapboxGLManager extends SimpleViewManager serializeTracking(int locationTracking, int bearingTracking) { + ArrayList result = new ArrayList(); + result.add(locationTracking); + result.add(bearingTracking); return result; } + public static final int[] locationTrackingModes = new int[] { + MyLocationTracking.TRACKING_NONE, + MyLocationTracking.TRACKING_FOLLOW, + MyLocationTracking.TRACKING_FOLLOW, + MyLocationTracking.TRACKING_FOLLOW + }; + + public static final int[] bearingTrackingModes = new int[] { + MyBearingTracking.NONE, + MyBearingTracking.NONE, + MyBearingTracking.GPS, + MyBearingTracking.COMPASS + }; + @Override public @Nullable Map getConstants() { HashMap constants = new HashMap(); @@ -56,11 +72,11 @@ public class ReactNativeMapboxGLModule extends ReactContextBaseJavaModule { HashMap userTrackingMode = new HashMap(); HashMap mapStyles = new HashMap(); -// // User tracking constants -// userTrackingMode.put("none", serializeTracking(MyLocationTracking.TRACKING_NONE, MyBearingTracking.NONE)); -// userTrackingMode.put("follow", serializeTracking(MyLocationTracking.TRACKING_FOLLOW, MyBearingTracking.NONE)); -// userTrackingMode.put("followWithCourse", serializeTracking(MyLocationTracking.TRACKING_FOLLOW, MyBearingTracking.GPS)); -// userTrackingMode.put("followWithHeading", serializeTracking(MyLocationTracking.TRACKING_FOLLOW, MyBearingTracking.COMPASS)); + // User tracking constants + userTrackingMode.put("none", 0); + userTrackingMode.put("follow", 1); + userTrackingMode.put("followWithCourse", 2); + userTrackingMode.put("followWithHeading", 3); // Style constants mapStyles.put("light", Style.LIGHT); diff --git a/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLView.java b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLView.java index 9b2a5ee..06a21a0 100644 --- a/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLView.java +++ b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLView.java @@ -1,27 +1,34 @@ package com.mapbox.reactnativemapboxgl; import android.content.Context; -import android.os.Bundle; import android.util.Log; +import android.widget.LinearLayout; import com.facebook.react.bridge.LifecycleEventListener; +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.MapboxMapOptions; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; -public class ReactNativeMapboxGLView extends MapView implements OnMapReadyCallback, LifecycleEventListener { +public class ReactNativeMapboxGLView extends LinearLayout implements OnMapReadyCallback, LifecycleEventListener { private MapboxMap _map = null; + private MapView _mapView = null; private ReactNativeMapboxGLManager _manager; - private String _styleURL; private boolean _paused = false; - private boolean _showsUserLocation = false; + private CameraPosition.Builder _initialCamera = new CameraPosition.Builder(); + private MapboxMapOptions _mapOptions; + private int _locationTrackingMode; + private int _bearingTrackingMode; + private boolean _showsUserLocation; public ReactNativeMapboxGLView(Context context, ReactNativeMapboxGLManager manager) { super(context); - this.getMapAsync(this); _manager = manager; + _mapOptions = MapboxMapOptions.createFromAttributes(context, null); } // Lifecycle methods @@ -29,9 +36,12 @@ public class ReactNativeMapboxGLView extends MapView implements OnMapReadyCallba @Override public void onAttachedToWindow () { super.onAttachedToWindow(); - onCreate(null); + if (_mapView == null) { + setupMapView(); + } + _mapView.onCreate(null); _paused = false; - onResume(); + _mapView.onResume(); _manager.getContext().addLifecycleEventListener(this); } @@ -40,49 +50,139 @@ public class ReactNativeMapboxGLView extends MapView implements OnMapReadyCallba super.onDetachedFromWindow(); if (!_paused) { _paused = true; - onPause(); + _mapView.onPause(); } - onDestroy(); + _mapView.onDestroy(); _manager.getContext().removeLifecycleEventListener(this); } @Override public void onHostResume() { _paused = false; - onResume(); + _mapView.onResume(); } @Override public void onHostPause() { _paused = true; - onPause(); + _mapView.onPause(); } @Override public void onHostDestroy() { - onDestroy(); + _mapView.onDestroy(); + } + + // Initialization + + private void setupMapView() { + _mapOptions.camera(_initialCamera.build()); + _mapView = new MapView(this.getContext(), _mapOptions); + _mapView.getMapAsync(this); + this.addView(_mapView); } @Override public void onMapReady(MapboxMap mapboxMap) { _map = mapboxMap; - _map.setStyleUrl(_styleURL); _map.setMyLocationEnabled(_showsUserLocation); + _map.getTrackingSettings().setMyLocationTrackingMode(_locationTrackingMode); + _map.getTrackingSettings().setMyBearingTrackingMode(_bearingTrackingMode); + + // If these settings changed between setupMapView() and onMapReady(), coerce them to their right values + if (_map.isDebugActive() != _mapOptions.getDebugActive()) { + _map.setDebugActive(_mapOptions.getDebugActive()); + } + if (!_map.getStyleUrl().equals(_mapOptions.getStyle())) { + _map.setStyleUrl(_mapOptions.getStyle()); + } + } + + // Utils + + private void assertNotChangeable(String propName) { + if (_mapView != null) { + Log.e(getContext().getPackageName(), "Changing MapView." + propName + " after component has been mounted is not currently supported"); + } } // Props - public void setStyleURL(String styleURL) { - if (_styleURL != null && _styleURL.equals(styleURL)) { - return; - } - _styleURL = styleURL; - if (_map != null) { _map.setStyleUrl(styleURL); } + public void setInitialZoomLevel(double value) { + _initialCamera.zoom(value); + } + + public void setInitialDirection(double value) { + _initialCamera.bearing(value); + } + + public void setInitialCenterCoordinate(double lat, double lon) { + _initialCamera.target(new LatLng(lat, lon)); } public void setShowsUserLocation(boolean value) { - if (_showsUserLocation != value) { return; } + if (_showsUserLocation == value) { return; } _showsUserLocation = value; if (_map != null) { _map.setMyLocationEnabled(value); } } + + public void setRotateEnabled(boolean value) { + if (_mapOptions.getRotateGesturesEnabled() == value) { return; } + _mapOptions.rotateGesturesEnabled(value); + assertNotChangeable("rotateEnabled"); + } + + public void setScrollEnabled(boolean value) { + if (_mapOptions.getScrollGesturesEnabled() == value) { return; } + _mapOptions.scrollGesturesEnabled(value); + assertNotChangeable("scrollEnabled"); + } + + public void setZoomEnabled(boolean value) { + if (_mapOptions.getZoomGesturesEnabled() == value) { return; } + _mapOptions.zoomGesturesEnabled(value); + assertNotChangeable("zoomEnabled"); + } + + public void setStyleURL(String styleURL) { + if (styleURL.equals(_mapOptions.getStyle())) { return; } + _mapOptions.styleUrl(styleURL); + if (_map != null) { _map.setStyleUrl(styleURL); } + } + + public void setDebugActive(boolean value) { + if (_mapOptions.getDebugActive() == value) { return; } + _mapOptions.debugActive(value); + if (_map != null) { _map.setDebugActive(value); }; + } + + public void setLocationTracking(int value) { + if (_locationTrackingMode == value) { return; } + _locationTrackingMode = value; + if (_map != null) { _map.getTrackingSettings().setMyLocationTrackingMode(value); }; + } + + public void setBearingTracking(int value) { + if (_bearingTrackingMode == value) { return; } + _bearingTrackingMode = value; + if (_map != null) { _map.getTrackingSettings().setMyBearingTrackingMode(value); }; + } + + public void setAttributionButtonIsHidden(boolean value) { + if (_mapOptions.getAttributionEnabled() == !value) { return; } + _mapOptions.attributionEnabled(!value); + assertNotChangeable("attributionButtonIsHidden"); + } + + public void setLogoIsHidden(boolean value) { + if (_mapOptions.getLogoEnabled() == !value) { return; } + _mapOptions.logoEnabled(!value); + assertNotChangeable("logoIsHidden"); + } + + public void setCompassIsHidden(boolean value) { + if (_mapOptions.getCompassEnabled() == !value) { return; } + _mapOptions.compassEnabled(!value); + assertNotChangeable("compassIsHidden"); + } } diff --git a/index.js b/index.js index bff2800..e109a30 100644 --- a/index.js +++ b/index.js @@ -167,15 +167,19 @@ class MapView extends Component { latitude: PropTypes.number.isRequired, longitude: PropTypes.number.isRequired }), - showsUserLocation: PropTypes.bool, + clipsToBounds: PropTypes.bool, + debugActive: PropTypes.bool, rotateEnabled: PropTypes.bool, scrollEnabled: PropTypes.bool, zoomEnabled: PropTypes.bool, + showsUserLocation: PropTypes.bool, styleURL: PropTypes.string.isRequired, - clipsToBounds: PropTypes.bool, - debugActive: PropTypes.bool, userTrackingMode: PropTypes.number, - attributionButton: PropTypes.bool, + attributionButtonIsHidden: PropTypes.bool, + logoIsHidden: PropTypes.bool, + compassIsHidden: PropTypes.bool, + userLocationVerticalAlignment: PropTypes.number, + annotations: PropTypes.arrayOf(PropTypes.shape({ coordinates: PropTypes.array.isRequired, title: PropTypes.string, @@ -199,9 +203,7 @@ class MapView extends Component { }) })), annotationsAreImmutable: PropTypes.bool, - attributionButtonIsHidden: PropTypes.bool, - logoIsHidden: PropTypes.bool, - compassIsHidden: PropTypes.bool, + onRegionChange: PropTypes.func, onRegionWillChange: PropTypes.func, onOpenAnnotation: PropTypes.func, @@ -213,7 +215,6 @@ class MapView extends Component { onLongPress: PropTypes.func, onTap: PropTypes.func, contentInset: PropTypes.array, - userLocationVerticalAlignment: PropTypes.number, onChangeUserTrackingMode: PropTypes.func, };