ReactNativeMapboxGLView.java 31.13 KiB
package com.mapbox.reactnativemapboxgl;
import android.content.Context;
import android.graphics.PointF;
import android.hardware.GeomagneticField;
import android.location.Location;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.UiThread;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.touch.OnInterceptTouchEventListener;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.google.common.collect.Sets;
import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.annotations.PolygonOptions;
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.annotations.MarkerView;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdate;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.UiSettings;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import android.graphics.Color;
public class ReactNativeMapboxGLView extends RelativeLayout implements
        OnMapReadyCallback, LifecycleEventListener,
        MapboxMap.OnMapClickListener, MapboxMap.OnMapLongClickListener,
        MapboxMap.OnMyBearingTrackingModeChangeListener, MapboxMap.OnMyLocationTrackingModeChangeListener,
        MapboxMap.OnMyLocationChangeListener,
        MapboxMap.OnMarkerClickListener, MapboxMap.OnInfoWindowClickListener,
        MapView.OnMapChangedListener, ReactNativeMapboxGLManager.ChildListener
    private MapboxMap _map = null;
    private MapView _mapView = null;
    private ReactNativeMapboxGLManager _manager;
    private boolean _paused = false;
    private CameraPosition.Builder _initialCamera = new CameraPosition.Builder();
    private MapboxMapOptions _mapOptions;
    private int _locationTrackingMode;
    private int _bearingTrackingMode;
    private boolean _trackingModeUpdateScheduled = false;
    private boolean _showsUserLocation;
    private boolean _annotationsPopUpEnabled = true;
    private boolean _zoomEnabled = true;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
private double _minimumZoomLevel = 0; private double _maximumZoomLevel = 20; private boolean _pitchEnabled = true; private boolean _scrollEnabled = true; private boolean _rotateEnabled = true; private boolean _enableOnRegionWillChange = false; private boolean _enableOnRegionDidChange = false; private int _paddingTop, _paddingRight, _paddingBottom, _paddingLeft; private boolean _recentlyChanged = false; private boolean _willChangeThrottled = false; private boolean _didChangeThrottled = false; private boolean _changeWasAnimated = false; private String _tintColor = "#F9650F"; private Map<String, Annotation> _annotations = new HashMap<>(); private Map<Long, String> _annotationIdsToName = new HashMap<>(); private Map<String, RNMGLAnnotationOptions> _annotationOptions = new HashMap<>(); private Map<String, MarkerView> _customAnnodationIds = new HashMap<>(); private Map<String, RNMGLAnnotationView> _customAnnotationViewMap = new HashMap<>(); private Map<RNMGLAnnotationView, RNMGLAnnotationView.PropertyListener> _propertyListeners = new HashMap<>(); private Handler _handler; @UiThread public ReactNativeMapboxGLView(Context context, ReactNativeMapboxGLManager manager) { super(context); _handler = new android.os.Handler(); _manager = manager; _mapOptions = MapboxMapOptions.createFromAttributes(context, null); _mapOptions.zoomGesturesEnabled(true); _mapOptions.rotateGesturesEnabled(true); _mapOptions.scrollGesturesEnabled(true); _mapOptions.tiltGesturesEnabled(true); } // Lifecycle methods public void onAfterUpdateTransaction() { if (_mapView != null) { return; } setupMapView(); _paused = false; _mapView.onResume(); _manager.getContext().addLifecycleEventListener(this); } public void onDrop() { if (_mapView == null) { return; } _manager.getContext().removeLifecycleEventListener(this); _manager.removeChildListener(this); if (!_paused) { _paused = true; _mapView.onPause(); } destroyMapView(); _mapView = null; } @Override public void onHostResume() { _paused = false; if (_mapView == null) { return; } _mapView.onResume(); } @Override public void onHostPause() { _paused = true; if (_mapView == null) { return; } _mapView.onPause();
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
} @Override public void onHostDestroy() { onDrop(); } // Initialization private void setupMapView() { _mapOptions.camera(_initialCamera.build()); _mapView = new MapView(this.getContext(), _mapOptions); _manager.addView(this, _mapView, 0); _mapView.addOnMapChangedListener(this); _mapView.onCreate(null); _mapView.getMapAsync(this); } @Override public void onMapReady(MapboxMap mapboxMap) { if (_mapView == null) { return; } _map = mapboxMap; // Configure map _map.setMyLocationEnabled(_showsUserLocation); _map.getTrackingSettings().setMyLocationTrackingMode(_locationTrackingMode); _map.getTrackingSettings().setMyBearingTrackingMode(_bearingTrackingMode); _map.setPadding(_paddingLeft, _paddingTop, _paddingRight, _paddingBottom); _map.setMinZoom(_minimumZoomLevel); _map.setMaxZoom(_maximumZoomLevel); // Customize the user location icon using the getMyLocationViewSettings object. _map.getMyLocationViewSettings().setForegroundTintColor(Color.parseColor(_tintColor)); _map.getMyLocationViewSettings().setAccuracyTintColor(Color.parseColor(_tintColor)); UiSettings uiSettings = _map.getUiSettings(); uiSettings.setZoomGesturesEnabled(_zoomEnabled); uiSettings.setScrollGesturesEnabled(_scrollEnabled); uiSettings.setRotateGesturesEnabled(_rotateEnabled); uiSettings.setTiltGesturesEnabled(_pitchEnabled); // If these settings changed between setupMapView() and onMapReady(), coerce them to their right values // This doesn't happen in the current implementation of MapView, but let's be future proof if (_map.isDebugActive() != _mapOptions.getDebugActive()) { _map.setDebugActive(_mapOptions.getDebugActive()); } if (!_map.getStyleUrl().equals(_mapOptions.getStyle())) { _map.setStyleUrl(_mapOptions.getStyle()); } if (uiSettings.isLogoEnabled() != _mapOptions.getLogoEnabled()) { uiSettings.setLogoEnabled(_mapOptions.getLogoEnabled()); } if (uiSettings.isAttributionEnabled() != _mapOptions.getAttributionEnabled()) { uiSettings.setAttributionEnabled(_mapOptions.getAttributionEnabled()); } if (uiSettings.isCompassEnabled() != _mapOptions.getCompassEnabled()) { uiSettings.setCompassEnabled(_mapOptions.getCompassEnabled()); } // Attach listeners _map.setOnMapClickListener(this); _map.setOnMapLongClickListener(this); _map.setOnMyLocationTrackingModeChangeListener(this); _map.setOnMyBearingTrackingModeChangeListener(this); _map.setOnMyLocationChangeListener(this); _map.setOnMarkerClickListener(this); _map.setOnInfoWindowClickListener(this); // Create annotations for (Map.Entry<String, RNMGLAnnotationOptions> entry : _annotationOptions.entrySet()) { Annotation annotation = entry.getValue().addToMap(_map);
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
_annotations.put(entry.getKey(), annotation); _annotationIdsToName.put(annotation.getId(), entry.getKey()); } _annotationOptions.clear(); _map.getMarkerViewManager().addMarkerViewAdapter( new RNMGLCustomMarkerViewAdapter(getContext())); } private void destroyMapView() { _mapView.removeOnMapChangedListener(this); if (_map != null) { _map.setOnMapClickListener(null); _map.setOnMapLongClickListener(null); _map.setOnMyLocationTrackingModeChangeListener(null); _map.setOnMyBearingTrackingModeChangeListener(null); _map.setOnMyLocationChangeListener(null); _map.setOnMarkerClickListener(null); _map.setOnInfoWindowClickListener(null); _map = null; } _mapView.onDestroy(); } // Children @Override public void childAdded(View child) { if (child instanceof RNMGLAnnotationView) { updateMarkerAnnotations(); } } @Override public void childRemoved(View child) { if (child instanceof RNMGLAnnotationView) { updateMarkerAnnotations(); } } private void updateMarkerAnnotations() { Set<RNMGLAnnotationView> newAnnotationViews = new HashSet<>(_manager.getAnnotationViews(this)); Set<RNMGLAnnotationView> currentViews = new HashSet<>(_customAnnotationViewMap.values()); Collection<RNMGLAnnotationView> addedChildren = Sets.difference(newAnnotationViews, currentViews); Collection<RNMGLAnnotationView> removedChildren = Sets.difference(currentViews, newAnnotationViews); for (RNMGLAnnotationView annotationView : removedChildren) { annotationView.removePropertyListener(_propertyListeners.get(annotationView)); _customAnnotationViewMap.remove(annotationView.getAnnotationId()); MarkerView markerView = _customAnnodationIds.remove(annotationView.getAnnotationId()); _map.removeMarker(markerView); } for (RNMGLAnnotationView annotationView : addedChildren) { _customAnnotationViewMap.put(annotationView.getAnnotationId(), annotationView); RNMGLCustomMarkerViewOptions options = new RNMGLCustomMarkerViewOptions() .annotationId(annotationView.getAnnotationId()) .position(annotationView.getCoordinate()) .anchor(0.5f, 0.5f) .flat(true); final MarkerView markerView = _map.addMarker(options); _customAnnodationIds.put(annotationView.getAnnotationId(), markerView); _annotationIdsToName.put(markerView.getId(), annotationView.getAnnotationId()); RNMGLAnnotationView.PropertyListener propertyListener = new RNMGLAnnotationView.PropertyListener() { @Override public void propertiesUpdated(RNMGLAnnotationView view) { markerView.setPosition(view.getCoordinate()); } };
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
annotationView.addPropertyListener(propertyListener); _propertyListeners.put(annotationView, propertyListener); } relayout(); } private void relayout() { // Need a relayout to show custom marker views _handler.post(new Runnable() { @Override public void run() { if(_mapView != null) { _mapView.measure( View.MeasureSpec.makeMeasureSpec(_mapView.getMeasuredWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(_mapView.getMeasuredHeight(), View.MeasureSpec.EXACTLY)); _mapView.layout(_mapView.getLeft(), _mapView.getTop(), _mapView.getRight(), _mapView.getBottom()); } } }); } // Props 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 setEnableOnRegionDidChange(boolean value) { _enableOnRegionDidChange = value; } public void setEnableOnRegionWillChange(boolean value) { _enableOnRegionWillChange = value; } public void setShowsUserLocation(boolean value) { if (_showsUserLocation == value) { return; } _showsUserLocation = value; if (_map != null) { _map.setMyLocationEnabled(value); } } public void setRotateEnabled(boolean value) { if (_rotateEnabled == value) { return; } _rotateEnabled = value; if (_map != null) { _map.getUiSettings().setRotateGesturesEnabled(value); } } public void setScrollEnabled(boolean value) { if (_scrollEnabled == value) { return; } _scrollEnabled = value; if (_map != null) { _map.getUiSettings().setScrollGesturesEnabled(value); } } public void setZoomEnabled(boolean value) { if (_zoomEnabled == value) { return; } _zoomEnabled = value; if (_map != null) {
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
_map.getUiSettings().setZoomGesturesEnabled(value); } } public void setMinimumZoomLevel(double value) { if (_minimumZoomLevel == value) { return; } _minimumZoomLevel = value; if (_map != null) { _map.setMinZoom(value); } } public void setMaximumZoomLevel(double value) { if (_maximumZoomLevel == value) { return; } _maximumZoomLevel = value; if (_map != null) { _map.setMaxZoom(value); } } public void setPitchEnabled(boolean value) { if (_pitchEnabled == value) { return; } _pitchEnabled = value; if (_map != null) { _map.getUiSettings().setTiltGesturesEnabled(value); } } public void setAnnotationsPopUpEnabled(boolean value) { _annotationsPopUpEnabled = value; } 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); if (_map != null) { _map.getUiSettings().setAttributionEnabled(!value); } } public void setLogoIsHidden(boolean value) { if (_mapOptions.getLogoEnabled() == !value) { return; } _mapOptions.logoEnabled(!value); if (_map != null) { _map.getUiSettings().setLogoEnabled(!value); }
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
} public void setCompassIsHidden(boolean value) { if (_mapOptions.getCompassEnabled() == !value) { return; } _mapOptions.compassEnabled(!value); if (_map != null) { _map.getUiSettings().setCompassEnabled(!value); } } public void setContentInset(int top, int right, int bottom, int left) { if (top == _paddingTop && bottom == _paddingBottom && left == _paddingLeft && right == _paddingRight) { return; } _paddingTop = top; _paddingRight = right; _paddingBottom = bottom; _paddingLeft = left; if (_map != null) { _map.setPadding(left, top, right, bottom); } } public void setTintColor(String value) { if (_tintColor == value) { return; } _tintColor = value; if (_map != null) { _map.getMyLocationViewSettings().setForegroundTintColor(Color.parseColor(_tintColor)); _map.getMyLocationViewSettings().setAccuracyTintColor(Color.parseColor(_tintColor)); } } // Events void emitEvent(String name, @Nullable WritableMap event) { if (event == null) { event = Arguments.createMap(); } ((ReactContext)getContext()) .getJSModule(RCTEventEmitter.class) .receiveEvent(getId(), name, event); } WritableMap serializePoint(LatLng point) { PointF screenCoords = _map.getProjection().toScreenLocation(point); WritableMap event = Arguments.createMap(); WritableMap src = Arguments.createMap(); src.putDouble("latitude", point.getLatitude()); src.putDouble("longitude", point.getLongitude()); src.putDouble("screenCoordX", screenCoords.x); src.putDouble("screenCoordY", screenCoords.y); event.putMap("src", src); return event; } @Override public void onMapClick(LatLng point) { emitEvent(ReactNativeMapboxGLEventTypes.ON_TAP, serializePoint(point)); } @Override public void onMapLongClick(@NonNull LatLng point) { emitEvent(ReactNativeMapboxGLEventTypes.ON_LONG_PRESS, serializePoint(point)); } @Override public void onMyLocationChange(@Nullable Location location) { WritableMap event = Arguments.createMap(); WritableMap src = Arguments.createMap();
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
if (location == null) { src.putString("message", "Could not get user location"); event.putMap("src", src); emitEvent(ReactNativeMapboxGLEventTypes.ON_LOCATE_USER_FAILED, event); return; } src.putDouble("latitude", location.getLatitude()); src.putDouble("longitude", location.getLongitude()); if (location.hasAccuracy()) { src.putDouble("verticalAccuracy", location.getAccuracy()); src.putDouble("horizontalAccuracy", location.getAccuracy()); } GeomagneticField geoField = new GeomagneticField( (float)location.getLatitude(), (float)location.getLongitude(), location.hasAltitude() ? (float)location.getAltitude() : 0.0f, System.currentTimeMillis() ); src.putDouble("magneticHeading", location.getBearing()); src.putDouble("trueHeading", location.getBearing() + geoField.getDeclination()); event.putMap("src", src); emitEvent(ReactNativeMapboxGLEventTypes.ON_UPDATE_USER_LOCATION, event); } class TrackingModeChangeRunnable implements Runnable { ReactNativeMapboxGLView target; TrackingModeChangeRunnable(ReactNativeMapboxGLView target) { this.target = target; } @Override public void run() { target.onTrackingModeChange(); } } public void onTrackingModeChange() { if (!_trackingModeUpdateScheduled) { return; } _trackingModeUpdateScheduled = false; for (int mode = 0; mode < ReactNativeMapboxGLModule.locationTrackingModes.length; mode++) { if (_locationTrackingMode == ReactNativeMapboxGLModule.locationTrackingModes[mode] && _bearingTrackingMode == ReactNativeMapboxGLModule.bearingTrackingModes[mode]) { WritableMap event = Arguments.createMap(); event.putInt("src", mode); emitEvent(ReactNativeMapboxGLEventTypes.ON_CHANGE_USER_TRACKING_MODE, event); break; } } } @Override @UiThread public void onMyBearingTrackingModeChange(int myBearingTrackingMode) { if (_bearingTrackingMode == myBearingTrackingMode) { return; } _bearingTrackingMode = myBearingTrackingMode; _trackingModeUpdateScheduled = true; _handler.post(new TrackingModeChangeRunnable(this)); } @Override @UiThread public void onMyLocationTrackingModeChange(int myLocationTrackingMode) { if (_locationTrackingMode == myLocationTrackingMode) { return; } _locationTrackingMode = myLocationTrackingMode;
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
_trackingModeUpdateScheduled = true; _handler.post(new TrackingModeChangeRunnable(this)); } WritableMap serializeCurrentRegion(boolean animated) { CameraPosition camera = _map == null ? _initialCamera.build() : _map.getCameraPosition(); WritableMap event = Arguments.createMap(); WritableMap src = Arguments.createMap(); src.putDouble("longitude", camera.target.getLongitude()); src.putDouble("latitude", camera.target.getLatitude()); src.putDouble("zoomLevel", camera.zoom); src.putDouble("direction", camera.bearing); src.putDouble("pitch", camera.tilt); src.putBoolean("animated", animated); event.putMap("src", src); return event; } class RegionChangedThrottleRunnable implements Runnable { ReactNativeMapboxGLView target; RegionChangedThrottleRunnable(ReactNativeMapboxGLView target) { this.target = target; } @Override public void run() { target.flushRegionChangedThrottle(true); } } private void flushRegionChangedThrottle(boolean fireAgain) { _recentlyChanged = false; if (_willChangeThrottled) { emitEvent(ReactNativeMapboxGLEventTypes.ON_REGION_WILL_CHANGE, serializeCurrentRegion(_changeWasAnimated)); } if (_didChangeThrottled) { emitEvent(ReactNativeMapboxGLEventTypes.ON_REGION_DID_CHANGE, serializeCurrentRegion(_changeWasAnimated)); } if (fireAgain && _didChangeThrottled) { _recentlyChanged = true; _handler.postDelayed(new RegionChangedThrottleRunnable(this), 100); } _willChangeThrottled = false; _didChangeThrottled = false; } private void onRegionWillChange(boolean animated) { if (animated) { flushRegionChangedThrottle(false); } if (_recentlyChanged) { _willChangeThrottled = true; _changeWasAnimated = animated; } else { emitEvent(ReactNativeMapboxGLEventTypes.ON_REGION_WILL_CHANGE, serializeCurrentRegion(animated)); } } private void onRegionDidChange(boolean animated) { if (animated) { flushRegionChangedThrottle(false); } if (_recentlyChanged) { _didChangeThrottled = true; _changeWasAnimated = animated;
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
} else { emitEvent(ReactNativeMapboxGLEventTypes.ON_REGION_DID_CHANGE, serializeCurrentRegion(animated)); _recentlyChanged = true; _handler.postDelayed(new RegionChangedThrottleRunnable(this), 100); } } @Override public void onMapChanged(int change) { switch (change) { case MapView.REGION_WILL_CHANGE: case MapView.REGION_WILL_CHANGE_ANIMATED: if (_enableOnRegionWillChange) { onRegionWillChange(change == MapView.REGION_WILL_CHANGE_ANIMATED); } break; case MapView.REGION_DID_CHANGE: case MapView.REGION_DID_CHANGE_ANIMATED: if (_enableOnRegionDidChange) { onRegionDidChange(change == MapView.REGION_DID_CHANGE_ANIMATED); } break; case MapView.WILL_START_LOADING_MAP: _manager.removeChildListener(this); emitEvent(ReactNativeMapboxGLEventTypes.ON_START_LOADING_MAP, null); break; case MapView.DID_FINISH_LOADING_MAP: _manager.addChildListener(this); updateMarkerAnnotations(); emitEvent(ReactNativeMapboxGLEventTypes.ON_FINISH_LOADING_MAP, null); break; } } WritableMap serializeMarker(Marker marker) { WritableMap event = Arguments.createMap(); WritableMap src = Arguments.createMap(); src.putString("id", _annotationIdsToName.get(marker.getId())); src.putDouble("longitude", marker.getPosition().getLongitude()); src.putDouble("latitude", marker.getPosition().getLatitude()); src.putString("title", marker.getTitle()); src.putString("subtitle", marker.getSnippet()); event.putMap("src", src); return event; } @Override public boolean onInfoWindowClick(@NonNull Marker marker) { emitEvent(ReactNativeMapboxGLEventTypes.ON_RIGHT_ANNOTATION_TAPPED, serializeMarker(marker)); return false; } @Override public boolean onMarkerClick(@NonNull Marker marker) { emitEvent(ReactNativeMapboxGLEventTypes.ON_OPEN_ANNOTATION, serializeMarker(marker)); if (_annotationsPopUpEnabled == false) { return true; } relayout(); return false; } // Getters public CameraPosition getCameraPosition() { if (_map == null) { return _initialCamera.build(); } return _map.getCameraPosition();
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
} public LatLngBounds getBounds() { if (_map == null) { return new LatLngBounds.Builder().build(); } return _map.getProjection().getVisibleRegion().latLngBounds; } public LatLng convertPointFromScreenLocation(PointF point) { if (_map == null) { return new LatLng(); } return _map.getProjection().fromScreenLocation(point); } public PointF convertPointToScreenLocation(LatLng point) { if (_map == null) { return new PointF(); } PointF screenCoords = _map.getProjection().toScreenLocation(point); return screenCoords; } // Camera setters public void setCameraPosition(CameraPosition position, int duration, @Nullable Runnable callback) { if (_map == null) { _initialCamera = new CameraPosition.Builder(position); if (callback != null) { callback.run(); } return; } CameraUpdate update = CameraUpdateFactory.newCameraPosition(position); setCameraUpdate(update, duration, callback); } public void setCameraUpdate(CameraUpdate update, int duration, @Nullable Runnable callback) { if (_map == null) { return; } if (duration == 0) { _map.moveCamera(update); if (callback != null) { callback.run(); } } else { // Ugh... Java callbacks suck class CameraCallback implements MapboxMap.CancelableCallback { Runnable callback; CameraCallback(Runnable callback) { this.callback = callback; } @Override public void onCancel() { if (callback != null) { callback.run(); } } @Override public void onFinish() { if (callback != null) { callback.run(); } } } _map.animateCamera(update, duration, new CameraCallback(callback)); } } // Annotations @Nullable Annotation _removeAnnotation(String name, boolean keep) { if (_map == null) { _annotationOptions.remove(name); return null; } Annotation annotation = _annotations.remove(name); if (annotation == null) { return null; } _annotationIdsToName.remove(annotation.getId());
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
if (keep) { return annotation; } _map.removeAnnotation(annotation); return null; } public void removeAnnotation(String name) { _removeAnnotation(name, false); } public void removeAllAnnotations() { _annotationOptions.clear(); _annotations.clear(); _annotationIdsToName.clear(); if (_map != null) { _map.removeAnnotations(); } } public void setAnnotation(String name, RNMGLAnnotationOptions options) { Annotation removed = _removeAnnotation(name, true); if (_map == null) { _annotationOptions.put(name, options); } else { Annotation annotation = options.addToMap(_map); _annotations.put(name, annotation); _annotationIdsToName.put(annotation.getId(), name); } if (removed != null) { _map.removeAnnotation(removed); } } public void selectAnnotation(String name, boolean animated) { if (_map == null) { return; } Annotation annotation = _annotations.get(name); if (annotation == null) { return; } if (!(annotation instanceof Marker)) { return; } Marker marker = (Marker)annotation; _map.selectMarker(marker); } public void deselectAnnotation() { if (_map == null) { return; } _map.deselectMarkers(); } // Custom Marker View Adapter - Adapts a MarkerView to display an custom react native view. private class RNMGLCustomMarkerViewAdapter extends MapboxMap.MarkerViewAdapter<RNMGLCustomMarkerView> { RNMGLCustomMarkerViewAdapter(@NonNull Context context) { super(context); } @Nullable @Override public View getView(@NonNull final RNMGLCustomMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) { RNMGLAnnotationView reactView = _customAnnotationViewMap.get(marker.getAnnotationId()); if (reactView.getParent() != null) { ViewGroup group = (ViewGroup) reactView.getParent(); group.removeView(reactView); } int width = (int)reactView.getLayoutWidth(); int height = (int)reactView.getLayoutHeight(); ViewGroup.LayoutParams frameLayoutMeasurements = new FrameLayout.LayoutParams(width, height); ViewGroup.LayoutParams viewGroupMeasurements = new ViewGroup.LayoutParams(width, height); FrameLayout layout; if (convertView == null) {
841842843844845846847848849850851852853854855856857858859860861862863
layout = new FrameLayout(getContext()); } else { layout = (FrameLayout) convertView; layout.removeAllViews(); } reactView.setLayoutParams(viewGroupMeasurements); reactView.setOnInterceptTouchEventListener(new OnInterceptTouchEventListener() { @Override public boolean onInterceptTouchEvent(ViewGroup v, MotionEvent event) { onMarkerClick(marker); return true; } }); layout.setLayoutParams(frameLayoutMeasurements); layout.addView(reactView); relayout(); return layout; } } }