diff --git a/android/rctmgl/src/main/java/mapbox/rctmgl/components/mapview/RCTMGLMapView.java b/android/rctmgl/src/main/java/mapbox/rctmgl/components/mapview/RCTMGLMapView.java index 10e9c6f..f9a5be8 100644 --- a/android/rctmgl/src/main/java/mapbox/rctmgl/components/mapview/RCTMGLMapView.java +++ b/android/rctmgl/src/main/java/mapbox/rctmgl/components/mapview/RCTMGLMapView.java @@ -3,6 +3,7 @@ package mapbox.rctmgl.components.mapview; import android.content.Context; import android.support.annotation.NonNull; import android.util.Log; +import android.view.View; import android.widget.RelativeLayout; import com.mapbox.mapboxsdk.camera.CameraPosition; @@ -204,11 +205,24 @@ public class RCTMGLMapView extends RelativeLayout implements //region Methods public void flyTo(Point flyToPoint, int durationMS) { + final IRCTMGLEvent event = new RCTMGLMapChangeEvent(this, RCTMGLEventTypes.FLY_TO_COMPLETE); + CameraPosition nextPosition = new CameraPosition.Builder(mMap.getCameraPosition()) .target(MGLGeoUtils.pointToLatLng(flyToPoint)) .build(); + CameraUpdate flyToUpdate = CameraUpdateFactory.newCameraPosition(nextPosition); - mMap.animateCamera(flyToUpdate, durationMS); + mMap.animateCamera(flyToUpdate, durationMS, new MapboxMap.CancelableCallback() { + @Override + public void onCancel() { + mManager.handleEvent(event); + } + + @Override + public void onFinish() { + mManager.handleEvent(event); + } + }); } //endregion @@ -276,11 +290,11 @@ public class RCTMGLMapView extends RelativeLayout implements } if (mMinZoomLevel != null) { - mMap.setMinZoomPreference(mMinZoomLevel.doubleValue()); + mMap.setMinZoomPreference(mMinZoomLevel); } if (mMaxZoomLevel != null) { - mMap.setMaxZoomPreference(mMaxZoomLevel.doubleValue()); + mMap.setMaxZoomPreference(mMaxZoomLevel); } } } diff --git a/android/rctmgl/src/main/java/mapbox/rctmgl/events/RCTMGLEventTypes.java b/android/rctmgl/src/main/java/mapbox/rctmgl/events/RCTMGLEventTypes.java index f674542..e01a3e8 100644 --- a/android/rctmgl/src/main/java/mapbox/rctmgl/events/RCTMGLEventTypes.java +++ b/android/rctmgl/src/main/java/mapbox/rctmgl/events/RCTMGLEventTypes.java @@ -25,4 +25,6 @@ public class RCTMGLEventTypes { public static final String DID_FINISH_RENDERING_MAP_FULLY = "didfinishrenderingmapfully"; public static final String DID_FINISH_LOADING_STYLE = "didfinishloadingstyle"; + + public static final String FLY_TO_COMPLETE = "flytocomplete"; } diff --git a/ios/RCTMGL/RCTMGLEventTypes.h b/ios/RCTMGL/RCTMGLEventTypes.h index ef18379..9dac17c 100644 --- a/ios/RCTMGL/RCTMGLEventTypes.h +++ b/ios/RCTMGL/RCTMGLEventTypes.h @@ -31,4 +31,6 @@ extern NSString *const RCT_MAPBOX_DID_FINISH_RENDERING_MAP_FULLY; extern NSString *const RCT_MAPBOX_DID_FINISH_LOADING_STYLE; +extern NSString *const RCT_MAPBOX_FLY_TO_COMPLETE; + @end diff --git a/ios/RCTMGL/RCTMGLEventTypes.m b/ios/RCTMGL/RCTMGLEventTypes.m index 11ee1cd..343329f 100644 --- a/ios/RCTMGL/RCTMGLEventTypes.m +++ b/ios/RCTMGL/RCTMGLEventTypes.m @@ -31,4 +31,6 @@ NSString *const RCT_MAPBOX_DID_FINISH_RENDERING_MAP_FULLY = @"didfinishrendering NSString *const RCT_MAPBOX_DID_FINISH_LOADING_STYLE = @"didfinishloadingstyle"; +NSString *const RCT_MAPBOX_FLY_TO_COMPLETE = @"flytocomplete"; + @end diff --git a/ios/RCTMGL/RCTMGLMapViewManager.m b/ios/RCTMGL/RCTMGLMapViewManager.m index 5e5589d..7aece9c 100644 --- a/ios/RCTMGL/RCTMGLMapViewManager.m +++ b/ios/RCTMGL/RCTMGLMapViewManager.m @@ -78,7 +78,10 @@ RCT_EXPORT_METHOD(flyTo:(nonnull NSNumber*)reactTag MGLMapCamera *camera = [reactMapView.camera copy]; camera.centerCoordinate = [RCTMGLUtils GeoJSONPoint:point]; CGFloat durationS = [durationMS doubleValue] * 0.001; - [reactMapView flyToCamera:camera withDuration:durationS completionHandler:nil]; + + [reactMapView flyToCamera:camera withDuration:durationS completionHandler:^{ + [self reactMapDidChange:reactMapView eventType:RCT_MAPBOX_FLY_TO_COMPLETE]; + }]; }]; } diff --git a/javascript/components/MapView.js b/javascript/components/MapView.js index 25d6a56..218a897 100644 --- a/javascript/components/MapView.js +++ b/javascript/components/MapView.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { requireNativeComponent } from 'react-native'; -import { isFunction, runNativeCommand } from '../utils'; +import { isFunction, runNativeCommand, noop } from '../utils'; const DEFAULT_CENTER_COORDINATE = { type: 'Point', @@ -27,8 +27,11 @@ class MapView extends React.Component { }; static EventTypes = { + // UI Interaction events Press: 'press', LongPress: 'longpress', + + // Map change events RegionWillChange: 'regionwillchange', RegionIsChanging: 'regionischanging', RegionDidChange: 'regiondidchange', @@ -42,6 +45,9 @@ class MapView extends React.Component { DidFinishRenderingMap: 'didfinishrenderingmap', DidFinishRenderingMapFully: 'didfinishrenderingmapfully', DidFinishLoadingStyle: 'didfinishloadingstyle', + + // Animation completion events + FlyToComplete: 'flytocomplete', }; static propTypes = { @@ -174,6 +180,11 @@ class MapView extends React.Component { * This event is triggered when a style has finished loading. */ onDidFinishLoadingStyle: PropTypes.func, + + /** + * This event is triggered when a fly to animation is cancelled or completed + */ + onFlyToComplete: PropTypes.func, }; static defaultProps = { @@ -261,6 +272,9 @@ class MapView extends React.Component { case MapView.EventTypes.DidFinishLoadingStyle: propName = 'onDidFinishLoadingStyle'; break; + case MapView.EventTypes.FlyToComplete: + propName = 'onFlyToComplete'; + break; } if (propName.length) { diff --git a/javascript/utils/index.js b/javascript/utils/index.js index b0402f5..4e01307 100644 --- a/javascript/utils/index.js +++ b/javascript/utils/index.js @@ -11,35 +11,19 @@ export function isFunction (fn) { } export function runNativeCommand (module, name, nativeRef, args = []) { - // android native command const managerInstance = NativeModules.UIManager[module]; if (!managerInstance) { throw new Error(`Could not find ${module}`); } - // get react tag so we can find, this component on the otherside const handle = findNodeHandle(nativeRef); + if (!handle) { + throw new Error(`Could not find handle for native ref ${module}.${name}`); + } + NativeModules.UIManager.dispatchViewManagerCommand( handle, managerInstance.Commands[name], args, ); - return; - // android native command - if (IS_ANDROID) { - return; - } - - // ios native command - const method = managerInstance[name]; - if (!method) { - throw new Error(`Could not find method ${name} on module ${module}`); - } - - method(handle, ...args); -} - -function getManagerInstance (module) { - const obj = IS_ANDROID ? NativeModules.UIManager : NativeModules; - return obj[module]; }