react-native-maps 2.0.0-beta.11 → 2.0.0-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -311,7 +311,7 @@ public class MapManager extends ViewGroupManager<MapView> {
311
311
  "onIndoorLevelActivated", MapBuilder.of("registrationName", "onIndoorLevelActivated"),
312
312
  "onIndoorBuildingFocused", MapBuilder.of("registrationName", "onIndoorBuildingFocused"),
313
313
  "onDoublePress", MapBuilder.of("registrationName", "onDoublePress"),
314
- "onMapLoaded", MapBuilder.of("registrationName", "onMapLoaded")
314
+ "onTilesRendered", MapBuilder.of("registrationName", "onTilesRendered")
315
315
  ));
316
316
 
317
317
  return map;
@@ -404,7 +404,7 @@ public class MapView extends com.google.android.gms.maps.MapView implements Goog
404
404
  map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
405
405
  @Override public void onMapLoaded() {
406
406
  isMapLoaded = true;
407
- manager.pushEvent(context, view, "onMapLoaded", new WritableNativeMap());
407
+ manager.pushEvent(context, view, "onTilesRendered", new WritableNativeMap());
408
408
  MapView.this.cacheView();
409
409
  }
410
410
  });
@@ -434,26 +434,34 @@ public class MapViewModule extends ReactContextBaseJavaModule {
434
434
  promise.reject("RNMMapView.map is not valid");
435
435
  return;
436
436
  }
437
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
438
-
439
437
  boolean addedPosition = false;
440
438
 
439
+ double maxLatitude = -Double.MAX_VALUE;
440
+ double minLatitude = Double.MAX_VALUE;
441
+ double maxLongitude = -Double.MAX_VALUE;
442
+ double minLongitude = Double.MAX_VALUE;
443
+
441
444
  for (MapFeature feature : view.features) {
442
445
  if (feature instanceof MapMarker) {
443
- Marker marker = (Marker) feature.getFeature();
444
- builder.include(marker.getPosition());
446
+ LatLng position = ((Marker) feature.getFeature()).getPosition();
447
+ maxLatitude = Math.max(maxLatitude, position.latitude);
448
+ minLatitude = Math.min(minLatitude, position.latitude);
449
+ maxLongitude = Math.max(maxLongitude, position.longitude);
450
+ minLongitude = Math.min(minLongitude, position.longitude);
445
451
  addedPosition = true;
446
452
  }
447
453
  // TODO(lmr): may want to include shapes / etc.
448
454
  }
449
- if (addedPosition) {
450
- LatLngBounds bounds = builder.build();
451
- CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, view.baseMapPadding);
452
-
453
- if (edgePadding != null) {
454
- view.map.setPadding(edgePadding.getInt("left"), edgePadding.getInt("top"),
455
- edgePadding.getInt("right"), edgePadding.getInt("bottom"));
456
- }
455
+ if(!addedPosition) {
456
+ // nothing to do
457
+ promise.resolve(null);
458
+ } else {
459
+ Map<String, Double> paddedBoundary = padBoundary(view, maxLatitude, minLatitude, maxLongitude, minLongitude, edgePadding);
460
+ LatLngBounds bounds = new LatLngBounds(
461
+ new LatLng(paddedBoundary.get("minLatitude"), paddedBoundary.get("minLongitude")), // southwest
462
+ new LatLng(paddedBoundary.get("maxLatitude"), paddedBoundary.get("maxLongitude")) // northeast
463
+ );
464
+ CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
457
465
 
458
466
  if (duration > 0) {
459
467
  view.map.animateCamera(cu, duration, new GoogleMap.CancelableCallback() {
@@ -491,7 +499,6 @@ public class MapViewModule extends ReactContextBaseJavaModule {
491
499
  promise.reject("RNMMapView.map is not valid");
492
500
  return;
493
501
  }
494
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
495
502
 
496
503
  String[] markerIDs = new String[markersIds.size()];
497
504
  for (int i = 0; i < markersIds.size(); i++) {
@@ -502,25 +509,35 @@ public class MapViewModule extends ReactContextBaseJavaModule {
502
509
 
503
510
  List<String> markerIDList = Arrays.asList(markerIDs);
504
511
 
512
+ double maxLatitude = -Double.MAX_VALUE;
513
+ double minLatitude = Double.MAX_VALUE;
514
+ double maxLongitude = -Double.MAX_VALUE;
515
+ double minLongitude = Double.MAX_VALUE;
516
+
505
517
  for (MapFeature feature : view.features) {
506
518
  if (feature instanceof MapMarker) {
507
519
  String identifier = ((MapMarker) feature).getIdentifier();
508
- Marker marker = (Marker) feature.getFeature();
509
520
  if (markerIDList.contains(identifier)) {
510
- builder.include(marker.getPosition());
521
+ LatLng position = ((Marker) feature.getFeature()).getPosition();
522
+ maxLatitude = Math.max(maxLatitude, position.latitude);
523
+ minLatitude = Math.min(minLatitude, position.latitude);
524
+ maxLongitude = Math.max(maxLongitude, position.longitude);
525
+ minLongitude = Math.min(minLongitude, position.longitude);
511
526
  addedPosition = true;
512
527
  }
513
528
  }
514
529
  }
515
530
 
516
- if (addedPosition) {
517
- LatLngBounds bounds = builder.build();
518
- CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, view.baseMapPadding);
519
-
520
- if (edgePadding != null) {
521
- view.map.setPadding(edgePadding.getInt("left"), edgePadding.getInt("top"),
522
- edgePadding.getInt("right"), edgePadding.getInt("bottom"));
523
- }
531
+ if(!addedPosition) {
532
+ // nothing to do
533
+ promise.resolve(null);
534
+ } else {
535
+ Map<String, Double> paddedBoundary = padBoundary(view, maxLatitude, minLatitude, maxLongitude, minLongitude, edgePadding);
536
+ LatLngBounds bounds = new LatLngBounds(
537
+ new LatLng(paddedBoundary.get("minLatitude"), paddedBoundary.get("minLongitude")), // southwest
538
+ new LatLng(paddedBoundary.get("maxLatitude"), paddedBoundary.get("maxLongitude")) // northeast
539
+ );
540
+ CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
524
541
 
525
542
  if (duration > 0) {
526
543
  view.map.animateCamera(cu, duration, new GoogleMap.CancelableCallback() {
@@ -558,21 +575,28 @@ public class MapViewModule extends ReactContextBaseJavaModule {
558
575
  return;
559
576
  }
560
577
 
561
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
578
+ double maxLatitude = -Double.MAX_VALUE;
579
+ double minLatitude = Double.MAX_VALUE;
580
+ double maxLongitude = -Double.MAX_VALUE;
581
+ double minLongitude = Double.MAX_VALUE;
562
582
 
563
583
  for (int i = 0; i < coordinates.size(); i++) {
564
584
  ReadableMap latLng = coordinates.getMap(i);
565
585
  double lat = latLng.getDouble("latitude");
566
586
  double lng = latLng.getDouble("longitude");
567
- builder.include(new LatLng(lat, lng));
587
+ maxLatitude = Math.max(maxLatitude, lat);
588
+ minLatitude = Math.min(minLatitude, lat);
589
+ maxLongitude = Math.max(maxLongitude, lng);
590
+ minLongitude = Math.min(minLongitude, lng);
568
591
  }
569
592
 
570
- LatLngBounds bounds = builder.build();
571
- CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, view.baseMapPadding);
593
+ Map<String, Double> paddedBoundary = padBoundary(view, maxLatitude, minLatitude, maxLongitude, minLongitude, edgePadding);
594
+ LatLngBounds bounds = new LatLngBounds(
595
+ new LatLng(paddedBoundary.get("minLatitude"), paddedBoundary.get("minLongitude")), // southwest
596
+ new LatLng(paddedBoundary.get("maxLatitude"), paddedBoundary.get("maxLongitude")) // northeast
597
+ );
572
598
 
573
- if (edgePadding != null) {
574
- view.appendMapPadding(edgePadding.getInt("left"), edgePadding.getInt("top"), edgePadding.getInt("right"), edgePadding.getInt("bottom"));
575
- }
599
+ CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
576
600
 
577
601
  if (duration > 0) {
578
602
  view.map.animateCamera(cu, duration, new GoogleMap.CancelableCallback() {
@@ -590,9 +614,29 @@ public class MapViewModule extends ReactContextBaseJavaModule {
590
614
  view.map.moveCamera(cu);
591
615
  promise.resolve(null);
592
616
  }
593
- // Move the google logo to the default base padding value.
594
- view.map.setPadding(view.baseLeftMapPadding, view.baseTopMapPadding, view.baseRightMapPadding, view.baseBottomMapPadding);
595
617
  }
596
618
  });
597
619
  }
620
+
621
+ private Map<String, Double> padBoundary(MapView mapView, double maxLat, double minLat, double maxLng, double minLng, ReadableMap edgePadding) {
622
+ double latitudeDelta = maxLat - minLat;
623
+ double longitudeDelta = maxLng - minLng;
624
+ float displayDensity = context.getResources().getDisplayMetrics().density;
625
+ double mapViewHeight = mapView.getHeight() / displayDensity;
626
+ double mapViewWidth = mapView.getWidth() / displayDensity;
627
+ double latPerHeight = latitudeDelta / mapViewHeight;
628
+ double lngPerWidth = longitudeDelta / mapViewWidth;
629
+ double paddedMaxLatitude = maxLat + latPerHeight * edgePadding.getInt("top");
630
+ double paddedMinLatitude = minLat - latPerHeight * edgePadding.getInt("bottom");
631
+ double paddedMaxLongitude = maxLng + lngPerWidth * edgePadding.getInt("right");
632
+ double paddedMinLongitude = minLng - lngPerWidth * edgePadding.getInt("left");
633
+
634
+ Map<String,Double> paddedBoundary = new HashMap<String,Double>();
635
+ paddedBoundary.put("maxLatitude", paddedMaxLatitude);
636
+ paddedBoundary.put("minLatitude", paddedMinLatitude);
637
+ paddedBoundary.put("maxLongitude", paddedMaxLongitude);
638
+ paddedBoundary.put("minLongitude", paddedMinLongitude);
639
+
640
+ return paddedBoundary;
641
+ }
598
642
  }
@@ -18,62 +18,61 @@
18
18
  @interface RNMGoogleMap : GMSMapView
19
19
 
20
20
  // TODO: don't use MK region?
21
- @property (nonatomic, weak) RCTBridge *bridge;
21
+ @property (nonatomic, assign) BOOL pitchEnabled;
22
+ @property (nonatomic, assign) BOOL rotateEnabled;
23
+ @property (nonatomic, assign) BOOL scrollDuringRotateOrZoomEnabled;
24
+ @property (nonatomic, assign) BOOL scrollEnabled;
25
+ @property (nonatomic, assign) BOOL showsBuildings;
26
+ @property (nonatomic, assign) BOOL showsCompass;
27
+ @property (nonatomic, assign) BOOL showsIndoorLevelPicker;
28
+ @property (nonatomic, assign) BOOL showsIndoors;
29
+ @property (nonatomic, assign) BOOL showsMyLocationButton;
30
+ @property (nonatomic, assign) BOOL showsTraffic;
31
+ @property (nonatomic, assign) BOOL showsUserLocation;
32
+ @property (nonatomic, assign) BOOL zoomEnabled;
33
+ @property (nonatomic, assign) BOOL zoomTapEnabled;
34
+ @property (nonatomic, assign) GMSCameraPosition *cameraProp; // Because the base class already has a "camera" prop.
22
35
  @property (nonatomic, assign) MKCoordinateRegion initialRegion;
23
36
  @property (nonatomic, assign) MKCoordinateRegion region;
24
- @property (nonatomic, assign) GMSCameraPosition *cameraProp; // Because the base class already has a "camera" prop.
25
- @property (nonatomic, strong) GMSCameraPosition *initialCamera;
26
37
  @property (nonatomic, assign) NSString *customMapStyleString;
27
- @property (nonatomic, assign) UIEdgeInsets mapPadding;
38
+ @property (nonatomic, assign) NSString *kmlSrc;
28
39
  @property (nonatomic, assign) NSString *paddingAdjustmentBehaviorString;
29
- @property (nonatomic, copy) RCTBubblingEventBlock onMapReady;
30
- @property (nonatomic, copy) RCTBubblingEventBlock onMapLoaded;
40
+ @property (nonatomic, assign) UIEdgeInsets mapPadding;
41
+ @property (nonatomic, copy) RCTBubblingEventBlock onChange;
31
42
  @property (nonatomic, copy) RCTBubblingEventBlock onKmlReady;
32
- @property (nonatomic, copy) RCTBubblingEventBlock onPress;
33
43
  @property (nonatomic, copy) RCTBubblingEventBlock onLongPress;
34
- @property (nonatomic, copy) RCTBubblingEventBlock onPanDrag;
35
- @property (nonatomic, copy) RCTBubblingEventBlock onUserLocationChange;
44
+ @property (nonatomic, copy) RCTBubblingEventBlock onMapReady;
36
45
  @property (nonatomic, copy) RCTBubblingEventBlock onMarkerPress;
37
- @property (nonatomic, copy) RCTBubblingEventBlock onChange;
46
+ @property (nonatomic, copy) RCTBubblingEventBlock onPanDrag;
38
47
  @property (nonatomic, copy) RCTBubblingEventBlock onPoiClick;
48
+ @property (nonatomic, copy) RCTBubblingEventBlock onPress;
49
+ @property (nonatomic, copy) RCTBubblingEventBlock onTilesRendered;
50
+ @property (nonatomic, copy) RCTBubblingEventBlock onUserLocationChange;
51
+ @property (nonatomic, copy) RCTDirectEventBlock onIndoorBuildingFocused;
52
+ @property (nonatomic, copy) RCTDirectEventBlock onIndoorLevelActivated;
39
53
  @property (nonatomic, copy) RCTDirectEventBlock onRegionChange;
40
54
  @property (nonatomic, copy) RCTDirectEventBlock onRegionChangeComplete;
41
- @property (nonatomic, copy) RCTDirectEventBlock onIndoorLevelActivated;
42
- @property (nonatomic, copy) RCTDirectEventBlock onIndoorBuildingFocused;
55
+ @property (nonatomic, strong) GMSCameraPosition *initialCamera;
56
+ @property (nonatomic, strong) NSMutableArray *circles;
57
+ @property (nonatomic, strong) NSMutableArray *heatmaps;
43
58
  @property (nonatomic, strong) NSMutableArray *markers;
59
+ @property (nonatomic, strong) NSMutableArray *overlays;
44
60
  @property (nonatomic, strong) NSMutableArray *polygons;
45
61
  @property (nonatomic, strong) NSMutableArray *polylines;
46
- @property (nonatomic, strong) NSMutableArray *circles;
47
- @property (nonatomic, strong) NSMutableArray *heatmaps;
48
62
  @property (nonatomic, strong) NSMutableArray *tiles;
49
- @property (nonatomic, strong) NSMutableArray *overlays;
50
-
51
- @property (nonatomic, assign) BOOL showsBuildings;
52
- @property (nonatomic, assign) BOOL showsTraffic;
53
- @property (nonatomic, assign) BOOL showsCompass;
54
- @property (nonatomic, assign) BOOL scrollEnabled;
55
- @property (nonatomic, assign) BOOL zoomEnabled;
56
- @property (nonatomic, assign) BOOL rotateEnabled;
57
- @property (nonatomic, assign) BOOL scrollDuringRotateOrZoomEnabled;
58
- @property (nonatomic, assign) BOOL pitchEnabled;
59
- @property (nonatomic, assign) BOOL zoomTapEnabled;
60
- @property (nonatomic, assign) BOOL showsUserLocation;
61
- @property (nonatomic, assign) BOOL showsMyLocationButton;
62
- @property (nonatomic, assign) BOOL showsIndoors;
63
- @property (nonatomic, assign) BOOL showsIndoorLevelPicker;
64
- @property (nonatomic, assign) NSString *kmlSrc;
63
+ @property (nonatomic, weak) RCTBridge *bridge;
65
64
 
66
- - (void)didPrepareMap;
67
- - (void)mapViewDidFinishTileRendering;
68
65
  - (BOOL)didTapMarker:(GMSMarker *)marker;
69
- - (void)didTapPolyline:(GMSPolyline *)polyline;
70
- - (void)didTapPolygon:(GMSPolygon *)polygon;
71
- - (void)didTapAtCoordinate:(CLLocationCoordinate2D)coordinate;
72
- - (void)didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate;
66
+ - (NSArray *)getMapBoundaries;
73
67
  - (void)didChangeCameraPosition:(GMSCameraPosition *)position isGesture:(BOOL)isGesture;
74
- - (void)idleAtCameraPosition:(GMSCameraPosition *)position isGesture:(BOOL)isGesture;
68
+ - (void)didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate;
69
+ - (void)didPrepareMap;
70
+ - (void)didTapAtCoordinate:(CLLocationCoordinate2D)coordinate;
75
71
  - (void)didTapPOIWithPlaceID:(NSString *)placeID name:(NSString *) name location:(CLLocationCoordinate2D) location;
76
- - (NSArray *)getMapBoundaries;
72
+ - (void)didTapPolygon:(GMSPolygon *)polygon;
73
+ - (void)didTapPolyline:(GMSPolyline *)polyline;
74
+ - (void)idleAtCameraPosition:(GMSCameraPosition *)position isGesture:(BOOL)isGesture;
75
+ - (void)mapViewDidFinishTileRendering;
77
76
 
78
77
  + (MKCoordinateRegion)makeGMSCameraPositionFromMap:(GMSMapView *)map andGMSCameraPosition:(GMSCameraPosition *)position;
79
78
  + (GMSCameraPosition*)makeGMSCameraPositionFromMap:(GMSMapView *)map andMKCoordinateRegion:(MKCoordinateRegion)region;
@@ -330,7 +330,7 @@ id regionAsJSON(MKCoordinateRegion region) {
330
330
  }
331
331
 
332
332
  - (void)mapViewDidFinishTileRendering {
333
- if (self.onMapLoaded) self.onMapLoaded(@{});
333
+ if (self.onTilesRendered) self.onTilesRendered(@{});
334
334
  }
335
335
 
336
336
  - (BOOL)didTapMarker:(GMSMarker *)marker {
@@ -81,7 +81,6 @@ RCT_EXPORT_VIEW_PROPERTY(onIndoorBuildingFocused, RCTDirectEventBlock)
81
81
  RCT_EXPORT_VIEW_PROPERTY(onIndoorLevelActivated, RCTDirectEventBlock)
82
82
  RCT_EXPORT_VIEW_PROPERTY(onKmlReady, RCTBubblingEventBlock)
83
83
  RCT_EXPORT_VIEW_PROPERTY(onLongPress, RCTBubblingEventBlock)
84
- RCT_EXPORT_VIEW_PROPERTY(onMapLoaded, RCTBubblingEventBlock)
85
84
  RCT_EXPORT_VIEW_PROPERTY(onMapReady, RCTBubblingEventBlock)
86
85
  RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock)
87
86
  RCT_EXPORT_VIEW_PROPERTY(onPanDrag, RCTBubblingEventBlock)
@@ -89,6 +88,7 @@ RCT_EXPORT_VIEW_PROPERTY(onPoiClick, RCTDirectEventBlock)
89
88
  RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)
90
89
  RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTDirectEventBlock)
91
90
  RCT_EXPORT_VIEW_PROPERTY(onRegionChangeComplete, RCTDirectEventBlock)
91
+ RCT_EXPORT_VIEW_PROPERTY(onTilesRendered, RCTBubblingEventBlock)
92
92
  RCT_EXPORT_VIEW_PROPERTY(onUserLocationChange, RCTBubblingEventBlock)
93
93
  RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL)
94
94
  RCT_EXPORT_VIEW_PROPERTY(region, MKCoordinateRegion)
@@ -261,17 +261,13 @@ RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag
261
261
 
262
262
  GMSCameraUpdate* cameraUpdate;
263
263
 
264
- if ([edgePadding count] != 0) {
265
- // Set Map viewport
266
- CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]];
267
- CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]];
268
- CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]];
269
- CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]];
264
+ // Set Map viewport
265
+ CGFloat top = [RCTConvert CGFloat:edgePadding[@"top"]];
266
+ CGFloat right = [RCTConvert CGFloat:edgePadding[@"right"]];
267
+ CGFloat bottom = [RCTConvert CGFloat:edgePadding[@"bottom"]];
268
+ CGFloat left = [RCTConvert CGFloat:edgePadding[@"left"]];
270
269
 
271
- cameraUpdate = [GMSCameraUpdate fitBounds:bounds withEdgeInsets:UIEdgeInsetsMake(top, left, bottom, right)];
272
- } else {
273
- cameraUpdate = [GMSCameraUpdate fitBounds:bounds withPadding:55.0f];
274
- }
270
+ cameraUpdate = [GMSCameraUpdate fitBounds:bounds withEdgeInsets:UIEdgeInsetsMake(top, left, bottom, right)];
275
271
  if (duration > 0.0f) {
276
272
  [CATransaction begin];
277
273
  [CATransaction setCompletionBlock:^{
package/ios/Maps/RNMMap.h CHANGED
@@ -66,6 +66,7 @@ extern const NSInteger RNMMapMaxZoomLevel;
66
66
  @property (nonatomic, copy) RCTDirectEventBlock onMarkerDragEnd;
67
67
  @property (nonatomic, copy) RCTDirectEventBlock onCalloutPress;
68
68
  @property (nonatomic, copy) RCTDirectEventBlock onRegionChange;
69
+ @property (nonatomic, copy) RCTBubblingEventBlock onTilesRendered;
69
70
  @property (nonatomic, copy) RCTBubblingEventBlock onUserLocationChange;
70
71
 
71
72
  - (void)cacheViewIfNeeded;
@@ -111,6 +111,7 @@ RCT_EXPORT_VIEW_PROPERTY(onMarkerPress, RCTDirectEventBlock)
111
111
  RCT_EXPORT_VIEW_PROPERTY(onMarkerSelect, RCTDirectEventBlock)
112
112
  RCT_EXPORT_VIEW_PROPERTY(onPanDrag, RCTBubblingEventBlock)
113
113
  RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)
114
+ RCT_EXPORT_VIEW_PROPERTY(onTilesRendered, RCTBubblingEventBlock)
114
115
  RCT_EXPORT_VIEW_PROPERTY(onUserLocationChange, RCTBubblingEventBlock)
115
116
  RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL)
116
117
  RCT_EXPORT_VIEW_PROPERTY(rotateEnabled, BOOL)
@@ -551,9 +552,12 @@ static int kDragCenterContext;
551
552
  [mapView beginLoading];
552
553
  }
553
554
 
554
- - (void)mapViewDidFinishRenderingMap:(RNMMap *)mapView fullyRendered:(BOOL)fullyRendered
555
+ - (void)mapViewDidFinishRenderingMap:(RNMMap *)mapView fullyRendered:(__unused BOOL)fullyRendered
555
556
  {
556
557
  [mapView finishLoading];
558
+ if (mapView.onTilesRendered) {
559
+ mapView.onTilesRendered(@{});
560
+ }
557
561
  }
558
562
 
559
563
  #pragma mark Private
@@ -287,21 +287,62 @@ RCT_EXPORT_METHOD(fitToElements:(nonnull NSNumber *)reactTag
287
287
  RCTLogError(@"Invalid view returned from registry, expecting RNMMap, got: %@", view);
288
288
  } else {
289
289
  RNMMap *mapView = (RNMMap *)view;
290
+
291
+ if(mapView.annotations.count < 1) {
292
+ resolve(nil);
293
+ } else {
294
+ CLLocationDegrees minLatitude = DBL_MAX;
295
+ CLLocationDegrees maxLatitude = -DBL_MAX;
296
+ CLLocationDegrees minLongitude = DBL_MAX;
297
+ CLLocationDegrees maxLongitude = -DBL_MAX;
298
+
299
+ for(id<MKAnnotation> annotation in mapView.annotations) {
300
+ double annotationLat = annotation.coordinate.latitude;
301
+ double annotationLong = annotation.coordinate.longitude;
302
+ minLatitude = fmin(annotationLat, minLatitude);
303
+ maxLatitude = fmax(annotationLat, maxLatitude);
304
+ minLongitude = fmin(annotationLong, minLongitude);
305
+ maxLongitude = fmax(annotationLong, maxLongitude);
306
+ }
307
+
308
+ double latitudeDelta = maxLatitude - minLatitude;
309
+ double longitudeDelta = maxLongitude - minLongitude;
310
+
311
+ double mapViewHeight = mapView.bounds.size.height;
312
+ double mapViewWidth = mapView.bounds.size.width;
313
+
314
+ double latPerHeight = latitudeDelta / mapViewHeight;
315
+ double lngPerWidth = longitudeDelta / mapViewWidth;
316
+
317
+ CGFloat topPadding = [RCTConvert CGFloat:edgePadding[@"top"]];
318
+ CGFloat rightPadding = [RCTConvert CGFloat:edgePadding[@"right"]];
319
+ CGFloat bottomPadding = [RCTConvert CGFloat:edgePadding[@"bottom"]];
320
+ CGFloat leftPadding = [RCTConvert CGFloat:edgePadding[@"left"]];
321
+
322
+ maxLatitude = maxLatitude + topPadding * latPerHeight;
323
+ minLatitude = minLatitude - bottomPadding * latPerHeight;
324
+ maxLongitude = maxLongitude + rightPadding * lngPerWidth;
325
+ minLongitude = minLongitude - leftPadding * lngPerWidth;
326
+
327
+ MKCoordinateRegion region;
328
+ region.center.latitude = (minLatitude + maxLatitude) / 2;
329
+ region.center.longitude = (minLongitude + maxLongitude) / 2;
330
+ // if fitting a single marker or if all markers are aligned, the delta will be zero (infinite zoom)
331
+ // this will cause mapkit not to zoom at all. Picking an arbitrary small number to circumvent
332
+ region.span.latitudeDelta = fmax(maxLatitude - minLatitude, 0.000001);
333
+ region.span.longitudeDelta = fmax(maxLongitude - minLongitude, 0.000001);
290
334
 
291
- // TODO(lmr): we potentially want to include overlays here... and could concat the two arrays together.
292
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
293
335
  if(duration > 0.0f) {
294
336
  [RNMMap animateWithDuration:duration/1000 animations:^{
295
- [mapView showAnnotations:mapView.annotations animated:YES];
337
+ [mapView setRegion:region animated:YES];
296
338
  } completion:^(BOOL finished){
297
339
  resolve(nil);
298
340
  }];
299
341
  } else {
300
- [mapView showAnnotations:mapView.annotations animated:NO];
342
+ [mapView setRegion:region animated:NO];
301
343
  resolve(nil);
302
344
  }
303
-
304
- });
345
+ }
305
346
  }
306
347
  }];
307
348
  }
@@ -328,17 +369,62 @@ RCT_EXPORT_METHOD(fitToSuppliedMarkers:(nonnull NSNumber *)reactTag
328
369
  }];
329
370
 
330
371
  NSArray *filteredMarkers = [mapView.annotations filteredArrayUsingPredicate:filterMarkers];
372
+
373
+ if(filteredMarkers.count < 1) {
374
+ resolve(nil);
375
+ } else {
376
+ CLLocationDegrees minLatitude = DBL_MAX;
377
+ CLLocationDegrees maxLatitude = -DBL_MAX;
378
+ CLLocationDegrees minLongitude = DBL_MAX;
379
+ CLLocationDegrees maxLongitude = -DBL_MAX;
380
+
381
+ for(id<MKAnnotation> annotation in filteredMarkers) {
382
+ double annotationLat = annotation.coordinate.latitude;
383
+ double annotationLong = annotation.coordinate.longitude;
384
+ minLatitude = fmin(annotationLat, minLatitude);
385
+ maxLatitude = fmax(annotationLat, maxLatitude);
386
+ minLongitude = fmin(annotationLong, minLongitude);
387
+ maxLongitude = fmax(annotationLong, maxLongitude);
388
+ }
389
+
390
+ double latitudeDelta = maxLatitude - minLatitude;
391
+ double longitudeDelta = maxLongitude - minLongitude;
392
+
393
+ double mapViewHeight = mapView.bounds.size.height;
394
+ double mapViewWidth = mapView.bounds.size.width;
395
+
396
+ double latPerHeight = latitudeDelta / mapViewHeight;
397
+ double lngPerWidth = longitudeDelta / mapViewWidth;
398
+
399
+ CGFloat topPadding = [RCTConvert CGFloat:edgePadding[@"top"]];
400
+ CGFloat rightPadding = [RCTConvert CGFloat:edgePadding[@"right"]];
401
+ CGFloat bottomPadding = [RCTConvert CGFloat:edgePadding[@"bottom"]];
402
+ CGFloat leftPadding = [RCTConvert CGFloat:edgePadding[@"left"]];
403
+
404
+ maxLatitude = maxLatitude + topPadding * latPerHeight;
405
+ minLatitude = minLatitude - bottomPadding * latPerHeight;
406
+ maxLongitude = maxLongitude + rightPadding * lngPerWidth;
407
+ minLongitude = minLongitude - leftPadding * lngPerWidth;
408
+
409
+ MKCoordinateRegion region;
410
+ region.center.latitude = (minLatitude + maxLatitude) / 2;
411
+ region.center.longitude = (minLongitude + maxLongitude) / 2;
412
+ // if fitting a single marker or if all markers are aligned, the delta will be zero (infinite zoom)
413
+ // this will cause mapkit not to zoom at all. Picking an arbitrary small number to circumvent
414
+ region.span.latitudeDelta = fmax(maxLatitude - minLatitude, 0.000001);
415
+ region.span.longitudeDelta = fmax(maxLongitude - minLongitude, 0.000001);
331
416
 
332
- if(duration > 0.0f) {
333
- [RNMMap animateWithDuration:duration/1000 animations:^{
334
- [mapView showAnnotations:filteredMarkers animated:YES];
335
- } completion:^(BOOL finished){
336
- resolve(nil);
337
- }];
417
+ if(duration > 0.0f) {
418
+ [RNMMap animateWithDuration:duration/1000 animations:^{
419
+ [mapView setRegion:region animated:YES];
420
+ } completion:^(BOOL finished){
421
+ resolve(nil);
422
+ }];
338
423
  } else {
339
- [mapView showAnnotations:filteredMarkers animated:NO];
424
+ [mapView setRegion:region animated:NO];
340
425
  resolve(nil);
341
426
  }
427
+ }
342
428
  }
343
429
  }];
344
430
  }
package/lib/MapView.d.ts CHANGED
@@ -227,13 +227,6 @@ export type MapViewProps = ViewProps & {
227
227
  * @platform Android: Supported
228
228
  */
229
229
  onLongPress?: (event: LongPressEvent) => void;
230
- /**
231
- * Callback that is called when the map has finished rendering all tiles.
232
- *
233
- * @platform iOS: Google Maps only
234
- * @platform Android: Supported
235
- */
236
- onMapLoaded?: (event: NativeSyntheticEvent<{}>) => void;
237
230
  /**
238
231
  * Callback that is called once the map is ready.
239
232
  *
@@ -329,6 +322,13 @@ export type MapViewProps = ViewProps & {
329
322
  * @platform Android: Supported
330
323
  */
331
324
  onRegionChangeComplete?: (region: Region, details: Details) => void;
325
+ /**
326
+ * Callback that is called when the map has finished rendering all tiles.
327
+ *
328
+ * @platform iOS: Supported
329
+ * @platform Android: Supported
330
+ */
331
+ onTilesRendered?: (event: NativeSyntheticEvent<{}>) => void;
332
332
  /**
333
333
  * Callback that is called when the underlying map figures our users current location
334
334
  * (coordinate also includes isFromMockProvider value for Android API 18 and above).
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "main": "lib/index.js",
6
6
  "author": "Leland Richardson <leland.m.richardson@gmail.com>",
7
7
  "homepage": "https://github.com/react-native-maps/react-native-maps#readme",
8
- "version": "2.0.0-beta.11",
8
+ "version": "2.0.0-beta.13",
9
9
  "license": "MIT",
10
10
  "scripts": {
11
11
  "lint": "eslint . --max-warnings 0",