react-native-maps 1.21.0-alpha.8 → 1.21.0-alpha.80

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.
Files changed (165) hide show
  1. package/android/build.gradle +45 -14
  2. package/android/generated/RCTAppDependencyProvider.h +25 -0
  3. package/android/generated/RCTAppDependencyProvider.mm +55 -0
  4. package/android/generated/RCTModulesConformingToProtocolsProvider.h +18 -0
  5. package/android/generated/RCTModulesConformingToProtocolsProvider.mm +33 -0
  6. package/android/generated/RCTThirdPartyComponentsProvider.h +16 -0
  7. package/android/generated/RCTThirdPartyComponentsProvider.mm +26 -0
  8. package/android/generated/ReactAppDependencyProvider.podspec +34 -0
  9. package/android/generated/java/com/facebook/fbreact/specs/NativeAirMapsModuleSpec.java +63 -0
  10. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsCalloutManagerDelegate.java +35 -0
  11. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsCalloutManagerInterface.java +18 -0
  12. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsGooglePolygonManagerDelegate.java +49 -0
  13. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsGooglePolygonManagerInterface.java +24 -0
  14. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsMapViewManagerDelegate.java +206 -0
  15. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsMapViewManagerInterface.java +74 -0
  16. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsMarkerManagerDelegate.java +104 -0
  17. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsMarkerManagerInterface.java +40 -0
  18. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsPolylineManagerDelegate.java +58 -0
  19. package/android/generated/java/com/facebook/react/viewmanagers/RNMapsPolylineManagerInterface.java +27 -0
  20. package/android/generated/jni/CMakeLists.txt +36 -0
  21. package/android/generated/jni/RNMapsSpecs-generated.cpp +68 -0
  22. package/android/generated/jni/RNMapsSpecs.h +31 -0
  23. package/android/generated/jni/react/renderer/components/RNMapsSpecs/ComponentDescriptors.cpp +27 -0
  24. package/android/generated/jni/react/renderer/components/RNMapsSpecs/ComponentDescriptors.h +29 -0
  25. package/android/generated/jni/react/renderer/components/RNMapsSpecs/EventEmitters.cpp +940 -0
  26. package/android/generated/jni/react/renderer/components/RNMapsSpecs/EventEmitters.h +809 -0
  27. package/android/generated/jni/react/renderer/components/RNMapsSpecs/Props.cpp +170 -0
  28. package/android/generated/jni/react/renderer/components/RNMapsSpecs/Props.h +1142 -0
  29. package/android/generated/jni/react/renderer/components/RNMapsSpecs/RNMapsSpecsJSI-generated.cpp +74 -0
  30. package/android/generated/jni/react/renderer/components/RNMapsSpecs/RNMapsSpecsJSI.h +268 -0
  31. package/android/generated/jni/react/renderer/components/RNMapsSpecs/ShadowNodes.cpp +22 -0
  32. package/android/generated/jni/react/renderer/components/RNMapsSpecs/ShadowNodes.h +87 -0
  33. package/android/generated/jni/react/renderer/components/RNMapsSpecs/States.cpp +16 -0
  34. package/android/generated/jni/react/renderer/components/RNMapsSpecs/States.h +89 -0
  35. package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  36. package/android/gradlew +1 -2
  37. package/android/src/main/java/com/rnmaps/fabric/CalloutManager.java +77 -0
  38. package/android/src/main/java/com/rnmaps/fabric/JSONUtil.java +86 -0
  39. package/android/src/main/java/com/rnmaps/fabric/MapViewManager.java +618 -0
  40. package/android/src/main/java/com/rnmaps/fabric/MarkerManager.java +259 -0
  41. package/android/src/main/java/com/rnmaps/fabric/NativeAirMapsModule.java +156 -4
  42. package/android/src/main/java/com/rnmaps/fabric/PolygonManager.java +89 -0
  43. package/android/src/main/java/com/rnmaps/fabric/PolylineManager.java +121 -0
  44. package/android/src/main/java/com/rnmaps/fabric/event/OnCalloutPressEvent.java +25 -0
  45. package/android/src/main/java/com/rnmaps/fabric/event/OnDeselectEvent.java +28 -0
  46. package/android/src/main/java/com/rnmaps/fabric/event/OnDoublePressEvent.java +27 -0
  47. package/android/src/main/java/com/rnmaps/fabric/event/OnDragEndEvent.java +28 -0
  48. package/android/src/main/java/com/rnmaps/fabric/event/OnDragEvent.java +28 -0
  49. package/android/src/main/java/com/rnmaps/fabric/event/OnDragStartEvent.java +28 -0
  50. package/android/src/main/java/com/rnmaps/fabric/event/OnIndoorBuildingFocusedEvent.java +28 -0
  51. package/android/src/main/java/com/rnmaps/fabric/event/OnIndoorLevelActivatedEvent.java +28 -0
  52. package/android/src/main/java/com/rnmaps/fabric/event/OnLongPressEvent.java +28 -0
  53. package/android/src/main/java/com/rnmaps/fabric/event/OnMapLoadedEvent.java +29 -0
  54. package/android/src/main/java/com/rnmaps/fabric/event/OnMapReadyEvent.java +29 -0
  55. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerDeselectEvent.java +28 -0
  56. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerDragEndEvent.java +28 -0
  57. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerDragEvent.java +28 -0
  58. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerDragStartEvent.java +28 -0
  59. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerPressEvent.java +28 -0
  60. package/android/src/main/java/com/rnmaps/fabric/event/OnMarkerSelectEvent.java +28 -0
  61. package/android/src/main/java/com/rnmaps/fabric/event/OnPanDragEvent.java +28 -0
  62. package/android/src/main/java/com/rnmaps/fabric/event/OnPoiClickEvent.java +27 -0
  63. package/android/src/main/java/com/rnmaps/fabric/event/OnPressEvent.java +27 -0
  64. package/android/src/main/java/com/rnmaps/fabric/event/OnRegionChangeCompleteEvent.java +30 -0
  65. package/android/src/main/java/com/rnmaps/fabric/event/OnRegionChangeEvent.java +48 -0
  66. package/android/src/main/java/com/rnmaps/fabric/event/OnRegionChangeStartEvent.java +33 -0
  67. package/android/src/main/java/com/rnmaps/fabric/event/OnSelectEvent.java +28 -0
  68. package/android/src/main/java/com/rnmaps/fabric/event/OnUserLocationChangeEvent.java +28 -0
  69. package/android/src/main/java/com/rnmaps/maps/MapAirModulePackage.java +30 -2
  70. package/android/src/main/java/com/rnmaps/maps/MapCallout.java +18 -0
  71. package/android/src/main/java/com/rnmaps/maps/MapManager.java +14 -14
  72. package/android/src/main/java/com/rnmaps/maps/MapMarker.java +79 -3
  73. package/android/src/main/java/com/rnmaps/maps/MapModule.java +206 -206
  74. package/android/src/main/java/com/rnmaps/maps/MapPolygon.java +29 -0
  75. package/android/src/main/java/com/rnmaps/maps/MapPolyline.java +207 -141
  76. package/android/src/main/java/com/rnmaps/maps/MapPolylineManager.java +1 -16
  77. package/android/src/main/java/com/rnmaps/maps/MapView.java +1649 -1336
  78. package/ios/AirGoogleMaps/AIRGoogleMap.h +3 -2
  79. package/ios/AirGoogleMaps/AIRGoogleMap.m +155 -50
  80. package/ios/AirGoogleMaps/AIRGoogleMapCircle.m +23 -11
  81. package/ios/AirGoogleMaps/AIRGoogleMapManager.m +17 -28
  82. package/ios/AirGoogleMaps/AIRGoogleMapMarker.h +2 -0
  83. package/ios/AirGoogleMaps/AIRGoogleMapMarker.m +347 -243
  84. package/ios/AirGoogleMaps/AIRGoogleMapPolygon.h +2 -1
  85. package/ios/AirGoogleMaps/AIRGoogleMapPolygon.m +30 -0
  86. package/ios/AirGoogleMaps/AIRGoogleMapPolyline.h +0 -1
  87. package/ios/AirGoogleMaps/AIRGoogleMapPolyline.m +0 -7
  88. package/ios/AirGoogleMaps/AIRGoogleMapWMSTile.h +1 -1
  89. package/ios/AirGoogleMaps/AIRGoogleMapWMSTile.m +2 -2
  90. package/ios/AirGoogleMaps/RCTConvert+GMSMapViewType.m +2 -0
  91. package/ios/AirGoogleMaps/RNMapsGoogleMapView.h +3 -3
  92. package/ios/AirGoogleMaps/RNMapsGoogleMapView.mm +201 -60
  93. package/ios/AirGoogleMaps/RNMapsGooglePolygonView.h +26 -0
  94. package/ios/AirGoogleMaps/RNMapsGooglePolygonView.mm +217 -0
  95. package/ios/AirGoogleMaps/RNMapsGooglePolygonViewManager.mm +25 -0
  96. package/ios/AirMaps/AIRMap.h +5 -2
  97. package/ios/AirMaps/AIRMap.m +285 -153
  98. package/ios/AirMaps/AIRMapManager.m +6 -0
  99. package/ios/AirMaps/AIRMapMarker.h +1 -0
  100. package/ios/AirMaps/AIRMapMarker.m +165 -103
  101. package/ios/AirMaps/Callout/SMCalloutView.m +1 -1
  102. package/ios/AirMaps/RNMapsAirModule.h +1 -1
  103. package/ios/AirMaps/RNMapsAirModule.mm +42 -172
  104. package/ios/AirMaps/RNMapsAirModuleDelegate.h +24 -0
  105. package/ios/AirMaps/RNMapsHostVewDelegate.h +17 -0
  106. package/ios/AirMaps/RNMapsMapView.h +3 -3
  107. package/ios/AirMaps/RNMapsMapView.mm +340 -308
  108. package/ios/AirMaps/RNMapsMarkerView.h +24 -0
  109. package/ios/AirMaps/RNMapsMarkerView.mm +430 -0
  110. package/ios/AirMaps/RNMapsMarkerViewManager.mm +21 -0
  111. package/ios/AirMaps/UIView +AirMap.m +20 -0
  112. package/ios/AirMaps/UIView+AirMap.h +11 -0
  113. package/ios/AirMaps.xcodeproj/project.pbxproj +60 -0
  114. package/ios/generated/RCTAppDependencyProvider.h +25 -0
  115. package/ios/generated/RCTAppDependencyProvider.mm +55 -0
  116. package/ios/generated/RCTModulesConformingToProtocolsProvider.h +18 -0
  117. package/ios/generated/RCTModulesConformingToProtocolsProvider.mm +33 -0
  118. package/ios/generated/RCTThirdPartyComponentsProvider.h +16 -0
  119. package/ios/generated/RCTThirdPartyComponentsProvider.mm +26 -0
  120. package/ios/generated/RNMapsSpecs/ComponentDescriptors.cpp +27 -0
  121. package/ios/generated/RNMapsSpecs/ComponentDescriptors.h +29 -0
  122. package/ios/generated/RNMapsSpecs/EventEmitters.cpp +940 -0
  123. package/ios/generated/RNMapsSpecs/EventEmitters.h +809 -0
  124. package/ios/generated/RNMapsSpecs/Props.cpp +170 -0
  125. package/ios/generated/RNMapsSpecs/Props.h +1142 -0
  126. package/ios/generated/RNMapsSpecs/RCTComponentViewHelpers.h +595 -0
  127. package/ios/generated/RNMapsSpecs/RNMapsSpecs-generated.mm +92 -0
  128. package/ios/generated/RNMapsSpecs/RNMapsSpecs.h +137 -0
  129. package/ios/generated/RNMapsSpecs/ShadowNodes.cpp +22 -0
  130. package/ios/generated/RNMapsSpecs/ShadowNodes.h +87 -0
  131. package/ios/generated/RNMapsSpecs/States.cpp +16 -0
  132. package/ios/generated/RNMapsSpecs/States.h +89 -0
  133. package/ios/generated/RNMapsSpecsJSI-generated.cpp +74 -0
  134. package/ios/generated/RNMapsSpecsJSI.h +268 -0
  135. package/ios/generated/ReactAppDependencyProvider.podspec +34 -0
  136. package/lib/MapCircle.d.ts +1 -1
  137. package/lib/MapHeatmap.d.ts +2 -2
  138. package/lib/MapHeatmap.js +1 -1
  139. package/lib/MapMarker.d.ts +16 -3
  140. package/lib/MapMarker.js +53 -9
  141. package/lib/MapMarkerNativeComponent.js +0 -2
  142. package/lib/MapOverlay.js +2 -8
  143. package/lib/MapPolygon.d.ts +1 -1
  144. package/lib/MapPolyline.d.ts +7 -7
  145. package/lib/MapView.d.ts +14 -27
  146. package/lib/MapView.js +97 -103
  147. package/lib/MapView.types.d.ts +1 -1
  148. package/lib/createFabricMap.d.ts +1 -0
  149. package/lib/createFabricMap.js +15 -2
  150. package/lib/decorateMapComponent.js +30 -0
  151. package/lib/specs/NativeAirMapsModule.d.ts +2 -2
  152. package/lib/specs/NativeComponentCallout.d.ts +46 -0
  153. package/lib/specs/NativeComponentCallout.js +9 -0
  154. package/lib/specs/NativeComponentGoogleMapView.d.ts +15 -15
  155. package/lib/specs/NativeComponentGoogleMapView.js +1 -0
  156. package/lib/specs/NativeComponentGooglePolygon.d.ts +75 -0
  157. package/lib/specs/NativeComponentGooglePolygon.js +7 -0
  158. package/lib/specs/NativeComponentMapView.d.ts +28 -36
  159. package/lib/specs/NativeComponentMapView.js +2 -3
  160. package/lib/specs/NativeComponentMarker.d.ts +258 -0
  161. package/lib/specs/NativeComponentMarker.js +19 -0
  162. package/lib/specs/NativeComponentPolyline.d.ts +101 -0
  163. package/lib/specs/NativeComponentPolyline.js +7 -0
  164. package/package.json +25 -20
  165. package/react-native-maps.podspec +2 -1
@@ -2,12 +2,16 @@ package com.rnmaps.maps;
2
2
 
3
3
  import static androidx.core.content.PermissionChecker.checkSelfPermission;
4
4
 
5
+ import android.app.Activity;
5
6
  import android.content.Context;
6
7
  import android.content.res.ColorStateList;
7
8
  import android.graphics.Bitmap;
8
9
  import android.graphics.Color;
9
10
  import android.graphics.Point;
10
11
  import android.location.Location;
12
+ import androidx.lifecycle.DefaultLifecycleObserver;
13
+ import androidx.lifecycle.LifecycleOwner;
14
+
11
15
  import android.util.Log;
12
16
  import android.view.GestureDetector;
13
17
  import android.view.MotionEvent;
@@ -23,9 +27,11 @@ import androidx.core.content.PermissionChecker;
23
27
  import androidx.core.view.GestureDetectorCompat;
24
28
  import androidx.core.view.MotionEventCompat;
25
29
 
30
+ import com.facebook.react.common.MapBuilder;
31
+
26
32
  import com.facebook.react.bridge.Arguments;
27
- import com.facebook.react.bridge.LifecycleEventListener;
28
33
  import com.facebook.react.bridge.ReactApplicationContext;
34
+ import com.facebook.react.bridge.ReactContext;
29
35
  import com.facebook.react.bridge.ReadableArray;
30
36
  import com.facebook.react.bridge.ReadableMap;
31
37
  import com.facebook.react.bridge.WritableArray;
@@ -34,13 +40,12 @@ import com.facebook.react.bridge.WritableNativeArray;
34
40
  import com.facebook.react.bridge.WritableNativeMap;
35
41
  import com.facebook.react.uimanager.ThemedReactContext;
36
42
  import com.facebook.react.uimanager.UIManagerHelper;
37
- import com.facebook.react.uimanager.common.UIManagerType;
43
+ import com.facebook.react.uimanager.events.Event;
38
44
  import com.facebook.react.uimanager.events.EventDispatcher;
39
45
  import com.google.android.gms.maps.CameraUpdate;
40
46
  import com.google.android.gms.maps.CameraUpdateFactory;
41
47
  import com.google.android.gms.maps.GoogleMap;
42
48
  import com.google.android.gms.maps.GoogleMapOptions;
43
- import com.google.android.gms.maps.MapsInitializer;
44
49
  import com.google.android.gms.maps.OnMapReadyCallback;
45
50
  import com.google.android.gms.maps.Projection;
46
51
  import com.google.android.gms.maps.model.BitmapDescriptorFactory;
@@ -65,8 +70,9 @@ import com.google.maps.android.collections.PolylineManager;
65
70
  import com.google.maps.android.data.kml.KmlContainer;
66
71
  import com.google.maps.android.data.kml.KmlLayer;
67
72
  import com.google.maps.android.data.kml.KmlPlacemark;
68
- import com.google.maps.android.data.kml.KmlStyle;
69
73
 
74
+ import org.json.JSONException;
75
+ import org.json.JSONObject;
70
76
  import org.xmlpull.v1.XmlPullParserException;
71
77
 
72
78
  import java.io.IOException;
@@ -78,1305 +84,1609 @@ import java.util.List;
78
84
  import java.util.Map;
79
85
  import java.util.concurrent.ExecutionException;
80
86
 
87
+ import com.rnmaps.fabric.event.*;
88
+
81
89
  public class MapView extends com.google.android.gms.maps.MapView implements GoogleMap.InfoWindowAdapter,
82
- GoogleMap.OnMarkerDragListener, OnMapReadyCallback, GoogleMap.OnPoiClickListener, GoogleMap.OnIndoorStateChangeListener {
83
- public GoogleMap map;
84
- private MarkerManager markerManager;
85
- private MarkerManager.Collection markerCollection;
86
- private PolylineManager polylineManager;
87
- private PolylineManager.Collection polylineCollection;
88
- private PolygonManager polygonManager;
89
- private PolygonManager.Collection polygonCollection;
90
- private CircleManager.Collection circleCollection;
91
- private GroundOverlayManager groundOverlayManager;
92
- private GroundOverlayManager.Collection groundOverlayCollection;
93
- private ProgressBar mapLoadingProgressBar;
94
- private RelativeLayout mapLoadingLayout;
95
- private ImageView cacheImageView;
96
- private Boolean isMapLoaded = false;
97
- private Integer loadingBackgroundColor = null;
98
- private Integer loadingIndicatorColor = null;
99
-
100
- private LatLngBounds boundsToMove;
101
- private CameraUpdate cameraToSet;
102
- private boolean setPaddingDeferred = false;
103
- private boolean showUserLocation = false;
104
- private boolean handlePanDrag = false;
105
- private boolean moveOnMarkerPress = true;
106
- private boolean cacheEnabled = false;
107
- private boolean poiClickEnabled = true;
108
-
109
- private ReadableMap initialRegion;
110
- private ReadableMap region;
111
- private ReadableMap initialCamera;
112
- private ReadableMap camera;
113
- private String customMapStyleString;
114
- private boolean initialRegionSet = false;
115
- private boolean initialCameraSet = false;
116
- private LatLngBounds cameraLastIdleBounds;
117
- private int cameraMoveReason = 0;
118
- private MapMarker selectedMarker;
119
-
120
- private static final String[] PERMISSIONS = new String[]{
121
- "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"};
122
-
123
- private final List<MapFeature> features = new ArrayList<>();
124
- private final Map<Marker, MapMarker> markerMap = new HashMap<>();
125
- private final Map<Polyline, MapPolyline> polylineMap = new HashMap<>();
126
- private final Map<Polygon, MapPolygon> polygonMap = new HashMap<>();
127
- private final Map<GroundOverlay, MapOverlay> overlayMap = new HashMap<>();
128
- private final Map<TileOverlay, MapHeatmap> heatmapMap = new HashMap<>();
129
- private final Map<TileOverlay, MapGradientPolyline> gradientPolylineMap = new HashMap<>();
130
- private final GestureDetectorCompat gestureDetector;
131
- private final MapManager manager;
132
- private LifecycleEventListener lifecycleListener;
133
- private boolean paused = false;
134
- private boolean destroyed = false;
135
- private final ThemedReactContext context;
136
- private final EventDispatcher eventDispatcher;
137
- private final FusedLocationSource fusedLocationSource;
138
-
139
- private final ViewAttacherGroup attacherGroup;
140
- private LatLng tapLocation;
141
-
142
- private static boolean contextHasBug(Context context) {
143
- return context == null ||
144
- context.getResources() == null ||
145
- context.getResources().getConfiguration() == null;
146
- }
147
-
148
- // We do this to fix this bug:
149
- // https://github.com/react-native-maps/react-native-maps/issues/271
150
- //
151
- // which conflicts with another bug regarding the passed in context:
152
- // https://github.com/react-native-maps/react-native-maps/issues/1147
153
- //
154
- // Doing this allows us to avoid both bugs.
155
- private static Context getNonBuggyContext(ThemedReactContext reactContext,
156
- ReactApplicationContext appContext) {
157
- Context superContext = reactContext;
158
- if (!contextHasBug(appContext.getCurrentActivity())) {
159
- superContext = appContext.getCurrentActivity();
160
- } else if (contextHasBug(superContext)) {
161
- // we have the bug! let's try to find a better context to use
162
- if (!contextHasBug(reactContext.getCurrentActivity())) {
163
- superContext = reactContext.getCurrentActivity();
164
- } else if (!contextHasBug(reactContext.getApplicationContext())) {
165
- superContext = reactContext.getApplicationContext();
166
- }
167
-
168
- }
169
- return superContext;
170
- }
171
-
172
- public MapView(ThemedReactContext reactContext, ReactApplicationContext appContext,
173
- MapManager manager,
174
- GoogleMapOptions googleMapOptions) {
175
- super(getNonBuggyContext(reactContext, appContext), googleMapOptions);
176
-
177
- this.manager = manager;
178
- this.context = reactContext;
179
- MapsInitializer.initialize(context, this.manager.renderer, renderer -> Log.d("AirMapRenderer", renderer.toString()));
90
+ GoogleMap.OnMarkerDragListener, OnMapReadyCallback, GoogleMap.OnPoiClickListener, GoogleMap.OnIndoorStateChangeListener, DefaultLifecycleObserver {
91
+ public GoogleMap map;
92
+ private MarkerManager markerManager;
93
+ private MarkerManager.Collection markerCollection;
94
+ private PolylineManager polylineManager;
95
+ private PolylineManager.Collection polylineCollection;
96
+ private PolygonManager polygonManager;
97
+ private PolygonManager.Collection polygonCollection;
98
+ private CircleManager.Collection circleCollection;
99
+ private GroundOverlayManager groundOverlayManager;
100
+ private GroundOverlayManager.Collection groundOverlayCollection;
101
+ private ProgressBar mapLoadingProgressBar;
102
+ private RelativeLayout mapLoadingLayout;
103
+ private ImageView cacheImageView;
104
+ private Boolean isMapLoaded = false;
105
+
106
+ private Boolean isMapReady = false;
107
+
108
+ private Integer loadingBackgroundColor = null;
109
+ private Integer loadingIndicatorColor = null;
110
+
111
+ private LatLngBounds boundsToMove;
112
+ private CameraUpdate cameraToSet;
113
+ private boolean setPaddingDeferred = false;
114
+ private boolean showUserLocation = false;
115
+
116
+ private boolean showsTraffic = false;
117
+
118
+ private boolean handlePanDrag = false;
119
+ private boolean moveOnMarkerPress = true;
120
+ private boolean cacheEnabled = false;
121
+ private boolean poiClickEnabled = true;
122
+
123
+ private ReadableMap initialRegion;
124
+ private ReadableMap region;
125
+ private ReadableMap initialCamera;
126
+ private ReadableMap camera;
127
+ private String customMapStyleString;
128
+ private boolean initialRegionSet = false;
129
+ private boolean initialCameraSet = false;
130
+ private LatLngBounds cameraLastIdleBounds;
131
+ private int cameraMoveReason = 0;
132
+ private MapMarker selectedMarker;
133
+
134
+ private static final String[] PERMISSIONS = new String[]{
135
+ "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"};
136
+
137
+ private final List<MapFeature> features = new ArrayList<>();
138
+ private final Map<Marker, MapMarker> markerMap = new HashMap<>();
139
+ private final Map<Polyline, MapPolyline> polylineMap = new HashMap<>();
140
+ private final Map<Polygon, MapPolygon> polygonMap = new HashMap<>();
141
+ private final Map<GroundOverlay, MapOverlay> overlayMap = new HashMap<>();
142
+ private final Map<TileOverlay, MapHeatmap> heatmapMap = new HashMap<>();
143
+ private final Map<TileOverlay, MapGradientPolyline> gradientPolylineMap = new HashMap<>();
144
+ private final GestureDetectorCompat gestureDetector;
145
+ private boolean paused = false;
146
+ private boolean destroyed = false;
147
+ private final ThemedReactContext context;
148
+ private final FusedLocationSource fusedLocationSource;
149
+
150
+ private final ViewAttacherGroup attacherGroup;
151
+ private LatLng tapLocation;
152
+ private Float maxZoomLevel;
153
+ private Float minZoomLevel;
154
+ private Boolean pitchEnabled;
155
+ private Boolean showsCompass;
156
+ private Boolean rotateEnabled;
157
+ private Boolean zoomEnabled;
158
+ private Boolean zoomControlEnabled;
159
+ private Boolean setShowBuildings;
160
+ private Boolean showsIndoorLevelPicker;
161
+ private Boolean showIndoors;
162
+ private Boolean scrollEnabled;
163
+ private Boolean scrollDuringRotateOrZoomEnabled;
164
+ private String kmlSrc = null;
165
+
166
+ private static boolean contextHasBug(Context context) {
167
+ return context == null ||
168
+ context.getResources() == null ||
169
+ context.getResources().getConfiguration() == null;
170
+ }
171
+
172
+ // We do this to fix this bug:
173
+ // https://github.com/react-native-maps/react-native-maps/issues/271
174
+ //
175
+ // which conflicts with another bug regarding the passed in context:
176
+ // https://github.com/react-native-maps/react-native-maps/issues/1147
177
+ //
178
+ // Doing this allows us to avoid both bugs.
179
+ private static Context getNonBuggyContext(ThemedReactContext reactContext,
180
+ ReactApplicationContext appContext) {
181
+ Context superContext = reactContext;
182
+ if (!contextHasBug(appContext.getCurrentActivity())) {
183
+ superContext = appContext.getCurrentActivity();
184
+ } else if (contextHasBug(superContext)) {
185
+ // we have the bug! let's try to find a better context to use
186
+ if (!contextHasBug(reactContext.getCurrentActivity())) {
187
+ superContext = reactContext.getCurrentActivity();
188
+ } else if (!contextHasBug(reactContext.getApplicationContext())) {
189
+ superContext = reactContext.getApplicationContext();
190
+ }
191
+
192
+ }
193
+ return superContext;
194
+ }
195
+
196
+
197
+ @Override
198
+ public void onCreate(LifecycleOwner owner) {
180
199
  super.onCreate(null);
181
- super.onResume();
182
- super.getMapAsync(this);
200
+ }
201
+
202
+ @Override
203
+ public void onStart(LifecycleOwner owner) {
204
+ super.onStart();
205
+ }
206
+ @Override
207
+ public void onResume(LifecycleOwner owner) {
208
+ if (hasPermissions() && map != null) {
209
+ //noinspection MissingPermission
210
+ map.setMyLocationEnabled(showUserLocation);
211
+ map.setLocationSource(fusedLocationSource);
212
+ }
213
+ synchronized (MapView.this) {
214
+ if (!destroyed) {
215
+ MapView.this.onResume();
216
+ }
217
+ paused = false;
218
+ }
219
+ }
220
+
221
+
222
+ @Override
223
+ public void onPause(LifecycleOwner owner){
224
+ super.onPause();
225
+ if (hasPermissions() && map != null) {
226
+ //noinspection MissingPermission
227
+ map.setMyLocationEnabled(false);
228
+ }
229
+ synchronized (MapView.this) {
230
+ if (!destroyed) {
231
+ MapView.this.onPause();
232
+ }
233
+ paused = true;
234
+ }
235
+ }
236
+
237
+ @Override
238
+ public void onStop(LifecycleOwner owner) {
239
+ super.onStop();
240
+ }
241
+
242
+ @Override
243
+ public void onDestroy(LifecycleOwner owner){
244
+ MapView.this.doDestroy();
245
+ }
246
+
247
+ public MapView(ThemedReactContext context,
248
+ GoogleMapOptions googleMapOptions) {
249
+ super(context, googleMapOptions);
250
+ this.context = context;
251
+ Activity activity = context.getCurrentActivity();
252
+ if (activity instanceof LifecycleOwner) {
253
+ ((LifecycleOwner) activity).getLifecycle().addObserver(this);
254
+ }
255
+ super.getMapAsync(this);
256
+
257
+ final MapView view = this;
258
+
259
+ fusedLocationSource = new FusedLocationSource(context);
260
+
261
+ gestureDetector =
262
+ new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() {
263
+
264
+ @Override
265
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
266
+ float distanceY) {
267
+ if (handlePanDrag) {
268
+ onPanDrag(e2);
269
+ }
270
+ return false;
271
+ }
272
+
273
+ @Override
274
+ public boolean onDoubleTap(MotionEvent ev) {
275
+ onDoublePress(ev);
276
+ return false;
277
+ }
278
+ });
279
+
280
+ this.addOnLayoutChangeListener(new OnLayoutChangeListener() {
281
+ @Override
282
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
283
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
284
+ if (!paused) {
285
+ MapView.this.cacheView();
286
+ }
287
+ }
288
+ });
289
+
290
+
291
+ // Set up a parent view for triggering visibility in subviews that depend on it.
292
+ // Mainly ReactImageView depends on Fresco which depends on onVisibilityChanged() event
293
+ attacherGroup = new ViewAttacherGroup(context);
294
+ LayoutParams attacherLayoutParams = new LayoutParams(0, 0);
295
+ attacherLayoutParams.width = 0;
296
+ attacherLayoutParams.height = 0;
297
+ attacherLayoutParams.leftMargin = 99999999;
298
+ attacherLayoutParams.topMargin = 99999999;
299
+ attacherGroup.setLayoutParams(attacherLayoutParams);
300
+ addView(attacherGroup);
301
+ }
302
+
303
+ public MapView(ThemedReactContext reactContext, ReactApplicationContext appContext,
304
+ MapManager manager,
305
+ GoogleMapOptions googleMapOptions) {
306
+ this(null, googleMapOptions);
307
+
308
+ }
309
+
310
+ public double[][] getMarkersFrames(boolean onlyVisible) {
311
+
312
+ LatLngBounds.Builder builder = new LatLngBounds.Builder();
313
+ boolean addedPosition = false;
314
+ LatLngBounds mapBounds = map.getProjection().getVisibleRegion().latLngBounds;
315
+ for (MapFeature feature : features) {
316
+ if (feature instanceof MapMarker) {
317
+ Marker marker = (Marker) feature.getFeature();
318
+ if (!onlyVisible ||
319
+ mapBounds.contains(marker.getPosition())) {
320
+ builder.include(marker.getPosition());
321
+ addedPosition = true;
322
+ }
323
+ }
324
+ }
325
+ if (addedPosition) {
326
+
327
+ LatLngBounds bounds = builder.build();
328
+ LatLng northEast = bounds.northeast;
329
+ LatLng southWest = bounds.southwest;
330
+
331
+ return new double[][]{
332
+ {northEast.longitude, northEast.latitude},
333
+ {southWest.longitude, southWest.latitude}
334
+ };
335
+ }
336
+ return null;
337
+ }
338
+
339
+ public void setShowsTraffic(boolean value) {
340
+ showsTraffic = value;
341
+ if (map != null){
342
+ map.setTrafficEnabled(value);
343
+ }
344
+ }
345
+
183
346
 
184
- final MapView view = this;
347
+ @FunctionalInterface
348
+ public interface EventCreator<T extends Event> {
349
+ T create(int surfaceId, int viewId, WritableMap payload);
350
+ }
351
+
352
+ private <T extends Event> void dispatchEvent(WritableMap payload, EventCreator<T> creator) {
353
+ dispatchEvent(payload, creator, getId(), context);
354
+ }
355
+
356
+ public static <T extends Event> void dispatchEvent(WritableMap payload, EventCreator<T> creator, int viewId, ReactContext context) {
357
+ // Cast context to ReactContext
358
+ ReactContext reactContext = context;
359
+
360
+ // Get the event dispatcher
361
+ EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, viewId);
362
+
363
+ // If there is a dispatcher, create and dispatch the event
364
+ if (eventDispatcher != null) {
365
+ int surfaceId = UIManagerHelper.getSurfaceId(reactContext);
366
+ T event = creator.create(surfaceId, viewId, payload);
367
+ eventDispatcher.dispatchEvent(event);
368
+ }
369
+ }
370
+
371
+ @Override
372
+ public void onMapReady(@NonNull final GoogleMap map) {
373
+ if (destroyed) {
374
+ return;
375
+ }
376
+ this.map = map;
377
+ if (maxZoomLevel != null) {
378
+ setMaxZoomLevel(maxZoomLevel);
379
+ }
380
+ if (minZoomLevel != null) {
381
+ setMinZoomLevel(minZoomLevel);
382
+ }
383
+ if (pitchEnabled != null) {
384
+ setPitchEnabled(pitchEnabled);
385
+ }
386
+ if (showsCompass != null) {
387
+ setShowsCompass(showsCompass);
388
+ }
389
+ if (rotateEnabled != null) {
390
+ setRotateEnabled(rotateEnabled);
391
+ }
392
+ if (zoomEnabled != null) {
393
+ setZoomEnabled(zoomEnabled);
394
+ }
395
+ if (zoomControlEnabled != null) {
396
+ setZoomControlEnabled(zoomControlEnabled);
397
+ }
398
+ if (setShowBuildings != null) {
399
+ setShowBuildings(setShowBuildings);
400
+ }
401
+ if (showsIndoorLevelPicker != null) {
402
+ setShowsIndoorLevelPicker(showsIndoorLevelPicker);
403
+ }
404
+ if (showIndoors != null) {
405
+ setShowIndoors(showIndoors);
406
+ }
407
+ if (scrollEnabled != null) {
408
+ setScrollEnabled(scrollEnabled);
409
+ }
410
+ if (scrollDuringRotateOrZoomEnabled != null) {
411
+ setScrollDuringRotateOrZoomEnabled(scrollDuringRotateOrZoomEnabled);
412
+ }
413
+
414
+ markerManager = new MarkerManager(map);
415
+ markerCollection = markerManager.newCollection();
416
+ polylineManager = new PolylineManager(map);
417
+ polylineCollection = polylineManager.newCollection();
418
+ polygonManager = new PolygonManager(map);
419
+ polygonCollection = polygonManager.newCollection();
420
+ CircleManager circleManager = new CircleManager(map);
421
+ circleCollection = circleManager.newCollection();
422
+ groundOverlayManager = new GroundOverlayManager(map);
423
+ groundOverlayCollection = groundOverlayManager.newCollection();
424
+
425
+ markerCollection.setInfoWindowAdapter(this);
426
+ markerCollection.setOnMarkerDragListener(this);
427
+ this.map.setOnIndoorStateChangeListener(this);
428
+
429
+ applyBridgedProps();
430
+ dispatchEvent(new WritableNativeMap(), OnMapReadyEvent::new);
431
+
432
+ final MapView view = this;
433
+
434
+ map.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
435
+ @Override
436
+ public void onMyLocationChange(Location location) {
437
+ WritableMap event = new WritableNativeMap();
438
+
439
+ WritableMap coordinate = new WritableNativeMap();
440
+ coordinate.putDouble("latitude", location.getLatitude());
441
+ coordinate.putDouble("longitude", location.getLongitude());
442
+ coordinate.putDouble("altitude", location.getAltitude());
443
+ coordinate.putDouble("timestamp", location.getTime());
444
+ coordinate.putDouble("accuracy", location.getAccuracy());
445
+ coordinate.putDouble("speed", location.getSpeed());
446
+ coordinate.putDouble("heading", location.getBearing());
447
+ coordinate.putBoolean("isFromMockProvider", location.isFromMockProvider());
448
+
449
+ event.putMap("coordinate", coordinate);
450
+ dispatchEvent(event, OnUserLocationChangeEvent::new);
451
+ }
452
+ });
453
+
454
+ markerCollection.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
455
+ @Override
456
+ public boolean onMarkerClick(@NonNull Marker marker) {
457
+ MapMarker airMapMarker = getMarkerMap(marker);
458
+
459
+ WritableMap eventData = makeClickEventData(marker.getPosition());
460
+ eventData.putString("action", "press");
461
+ eventData.putString("id", airMapMarker.getIdentifier());
462
+ airMapMarker.dispatchEvent(eventData, OnPressEvent::new);
463
+
464
+ WritableMap mapEventData = makeClickEventData(marker.getPosition());
465
+ mapEventData.putString("action", "marker-press");
466
+ mapEventData.putString("id", airMapMarker.getIdentifier());
467
+
468
+ dispatchEvent(mapEventData, OnMarkerPressEvent::new);
469
+
470
+
471
+ handleMarkerSelection(airMapMarker);
472
+
473
+ // Return false to open the callout info window and center on the marker
474
+ // https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap
475
+ // .OnMarkerClickListener
476
+ if (view.moveOnMarkerPress) {
477
+ return false;
478
+ } else {
479
+ marker.showInfoWindow();
480
+ return true;
481
+ }
482
+ }
483
+ });
484
+
485
+ polygonCollection.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() {
486
+ @Override
487
+ public void onPolygonClick(@NonNull Polygon polygon) {
488
+ WritableMap event = makeClickEventData(tapLocation);
489
+ event.putString("action", "polygon-press");
490
+ MapPolygon mapPolygon = polygonMap.get(polygon);
491
+ mapPolygon.dispatchEvent(event, OnPressEvent::new, context);
492
+ event = makeClickEventData(tapLocation);
493
+ event.putString("action", "polygon-press");
494
+ event.putString("id", String.valueOf(mapPolygon.getId()));
495
+ dispatchEvent(event, OnPressEvent::new);
496
+ }
497
+ });
498
+
499
+ polylineCollection.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() {
500
+ @Override
501
+ public void onPolylineClick(@NonNull Polyline polyline) {
502
+ WritableMap event = makeClickEventData(tapLocation);
503
+ event.putString("action", "polyline-press");
504
+ // todo: use Fabric events
505
+ // manager.pushEvent(context, polylineMap.get(polyline), "onPress", event);
506
+ }
507
+ });
508
+
509
+ markerCollection.setOnInfoWindowClickListener(marker -> {
510
+ WritableMap event = makeClickEventData(marker.getPosition());
511
+ event.putString("action", "callout-press");
512
+ dispatchEvent(event, OnCalloutPressEvent::new);
513
+
514
+
515
+ event = makeClickEventData(marker.getPosition());
516
+ event.putString("action", "callout-press");
517
+ MapMarker markerView = getMarkerMap(marker);
518
+ dispatchEvent(event, OnCalloutPressEvent::new, markerView.getId(), context);
519
+
520
+ MapCallout infoWindow = markerView.getCalloutView();
521
+ if (infoWindow != null) {
522
+ event = makeClickEventData(marker.getPosition());
523
+ event.putString("action", "callout-press");
524
+ dispatchEvent(event, OnPressEvent::new, infoWindow.getId(), context);
525
+ }
526
+ });
527
+
528
+ map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
529
+ @Override
530
+ public void onMapClick(@NonNull LatLng point) {
531
+ WritableMap event = makeClickEventData(point);
532
+ event.putString("action", "press");
533
+ dispatchEvent(event, OnPressEvent::new);
534
+
535
+ handleMarkerSelection(null);
536
+ }
537
+ });
538
+
539
+ map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
540
+ @Override
541
+ public void onMapLongClick(@NonNull LatLng point) {
542
+ WritableMap event = makeClickEventData(point);
543
+ event.putString("action", "long-press");
544
+ dispatchEvent(event, OnLongPressEvent::new);
545
+ }
546
+ });
547
+
548
+ groundOverlayCollection.setOnGroundOverlayClickListener(new GoogleMap.OnGroundOverlayClickListener() {
549
+ @Override
550
+ public void onGroundOverlayClick(@NonNull GroundOverlay groundOverlay) {
551
+ WritableMap event = makeClickEventData(groundOverlay.getPosition());
552
+ event.putString("action", "overlay-press");
553
+ // todo: use Fabric events
554
+ // manager.pushEvent(context, overlayMap.get(groundOverlay), "onPress", event);
555
+ }
556
+ });
557
+
558
+ map.setOnCameraMoveStartedListener(reason -> {
559
+ cameraMoveReason = reason;
560
+ boolean isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == reason;
561
+ WritableMap event = new WritableNativeMap();
562
+ event.putBoolean("isGesture", isGesture);
563
+ dispatchEvent(event, OnRegionChangeStartEvent::new);
564
+ });
185
565
 
186
- fusedLocationSource = new FusedLocationSource(context);
566
+ map.setOnCameraMoveListener(() -> {
567
+ LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
568
+ cameraLastIdleBounds = null;
569
+ boolean isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == cameraMoveReason;
570
+ WritableMap payload = OnRegionChangeEvent.payLoadFor(bounds, false, isGesture);
571
+ dispatchEvent(payload, OnRegionChangeStartEvent::new);
572
+ });
187
573
 
188
- gestureDetector =
189
- new GestureDetectorCompat(reactContext, new GestureDetector.SimpleOnGestureListener() {
574
+ map.setOnCameraIdleListener(() -> {
575
+ LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
576
+ if ((cameraMoveReason != 0) &&
577
+ ((cameraLastIdleBounds == null) ||
578
+ LatLngBoundsUtils.BoundsAreDifferent(bounds, cameraLastIdleBounds))) {
190
579
 
191
- @Override
192
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
193
- float distanceY) {
194
- if (handlePanDrag) {
195
- onPanDrag(e2);
580
+ cameraLastIdleBounds = bounds;
581
+ boolean isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == cameraMoveReason;
582
+ WritableMap payload = OnRegionChangeEvent.payLoadFor(bounds, false, isGesture);
583
+ dispatchEvent(payload, OnRegionChangeCompleteEvent::new);
196
584
  }
197
- return false;
198
- }
199
-
200
- @Override
201
- public boolean onDoubleTap(MotionEvent ev) {
202
- onDoublePress(ev);
203
- return false;
204
- }
205
585
  });
206
586
 
207
- this.addOnLayoutChangeListener(new OnLayoutChangeListener() {
208
- @Override public void onLayoutChange(View v, int left, int top, int right, int bottom,
209
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
587
+ map.setOnMapLoadedCallback(() -> {
588
+ isMapLoaded = true;
589
+ dispatchEvent(new WritableNativeMap(), OnMapLoadedEvent::new);
590
+ MapView.this.cacheView();
591
+ });
592
+
593
+
594
+ map.setTrafficEnabled(showsTraffic);
595
+
596
+
597
+ isMapReady = true;
598
+ if (kmlSrc != null){
599
+ setKmlSrc(kmlSrc);
600
+ kmlSrc = null;
601
+ }
602
+ }
603
+
604
+ private synchronized void handleMarkerSelection(MapMarker target) {
605
+ if (selectedMarker == target) {
606
+ return;
607
+ }
608
+
609
+ WritableMap event;
610
+
611
+ if (selectedMarker != null) {
612
+ event = makeClickEventData(selectedMarker.getPosition());
613
+ event.putString("action", "marker-deselect");
614
+ event.putString("id", selectedMarker.getIdentifier());
615
+ selectedMarker.dispatchEvent(event, OnDeselectEvent::new);
616
+
617
+ event = makeClickEventData(selectedMarker.getPosition());
618
+ event.putString("action", "marker-deselect");
619
+ event.putString("id", selectedMarker.getIdentifier());
620
+ dispatchEvent(event, OnMarkerDeselectEvent::new);
621
+ }
622
+
623
+ if (target != null) {
624
+ event = makeClickEventData(target.getPosition());
625
+ event.putString("action", "marker-select");
626
+ event.putString("id", target.getIdentifier());
627
+ target.dispatchEvent(event, OnSelectEvent::new);
628
+
629
+ event = makeClickEventData(target.getPosition());
630
+ event.putString("action", "marker-select");
631
+ event.putString("id", target.getIdentifier());
632
+ dispatchEvent(event, OnMarkerSelectEvent::new);
633
+ }
634
+
635
+ selectedMarker = target;
636
+ }
637
+
638
+ private boolean hasPermissions() {
639
+ return checkSelfPermission(getContext(), PERMISSIONS[0]) == PermissionChecker.PERMISSION_GRANTED ||
640
+ checkSelfPermission(getContext(), PERMISSIONS[1]) == PermissionChecker.PERMISSION_GRANTED;
641
+ }
642
+
643
+
644
+ public static Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
645
+ MapBuilder.Builder<String, Object> builder = MapBuilder.builder();
646
+ builder.put(OnMarkerPressEvent.EVENT_NAME, MapBuilder.of("registrationName", OnMarkerPressEvent.EVENT_NAME));
647
+ builder.put(OnPressEvent.EVENT_NAME, MapBuilder.of("registrationName", OnPressEvent.EVENT_NAME));
648
+ builder.put(OnMarkerSelectEvent.EVENT_NAME, MapBuilder.of("registrationName", OnMarkerSelectEvent.EVENT_NAME));
649
+ builder.put(OnMarkerDeselectEvent.EVENT_NAME, MapBuilder.of("registrationName", OnMarkerDeselectEvent.EVENT_NAME));
650
+ builder.put(OnMarkerDragEvent.EVENT_NAME, MapBuilder.of("registrationName", OnMarkerDragEvent.EVENT_NAME));
651
+ builder.put(OnMarkerDragStartEvent.EVENT_NAME, MapBuilder.of("registrationName", OnMarkerDragStartEvent.EVENT_NAME));
652
+ builder.put(OnMarkerDragEndEvent.EVENT_NAME, MapBuilder.of("registrationName", OnMarkerDragEndEvent.EVENT_NAME));
653
+ builder.put(OnPoiClickEvent.EVENT_NAME, MapBuilder.of("registrationName", OnPoiClickEvent.EVENT_NAME));
654
+ builder.put(OnLongPressEvent.EVENT_NAME, MapBuilder.of("registrationName", OnLongPressEvent.EVENT_NAME));
655
+ builder.put(OnRegionChangeStartEvent.EVENT_NAME, MapBuilder.of("registrationName", OnRegionChangeStartEvent.EVENT_NAME));
656
+ builder.put(OnDoublePressEvent.EVENT_NAME, MapBuilder.of("registrationName", OnDoublePressEvent.EVENT_NAME));
657
+ builder.put(OnPanDragEvent.EVENT_NAME, MapBuilder.of("registrationName", OnPanDragEvent.EVENT_NAME));
658
+ return builder.build();
659
+ }
660
+
661
+ public static Map<String, Object> getExportedCustomDirectEventTypeConstants() {
662
+ return MapBuilder.of(
663
+ OnMapReadyEvent.EVENT_NAME, MapBuilder.of("registrationName", OnMapReadyEvent.EVENT_NAME),
664
+ OnUserLocationChangeEvent.EVENT_NAME, MapBuilder.of("registrationName", OnUserLocationChangeEvent.EVENT_NAME),
665
+ OnRegionChangeEvent.EVENT_NAME, MapBuilder.of("registrationName", OnRegionChangeEvent.EVENT_NAME),
666
+ OnIndoorBuildingFocusedEvent.EVENT_NAME, MapBuilder.of("registrationName", OnIndoorBuildingFocusedEvent.EVENT_NAME),
667
+ OnIndoorLevelActivatedEvent.EVENT_NAME, MapBuilder.of("registrationName", OnIndoorLevelActivatedEvent.EVENT_NAME)
668
+ );
669
+ }
670
+
671
+
672
+ /*
673
+ onDestroy is final method so I can't override it.
674
+ */
675
+ public synchronized void doDestroy() {
676
+ if (destroyed) {
677
+ return;
678
+ }
679
+ destroyed = true;
680
+
681
+ Activity activity = context.getCurrentActivity();
682
+ if (activity instanceof LifecycleOwner) {
683
+ ((LifecycleOwner) activity).getLifecycle().removeObserver(this);
684
+ }
210
685
  if (!paused) {
211
- MapView.this.cacheView();
212
- }
213
- }
214
- });
215
-
216
- int uiManagerType = UIManagerType.DEFAULT;
217
- if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
218
- uiManagerType = UIManagerType.FABRIC;
219
- }
220
-
221
- eventDispatcher = UIManagerHelper
222
- .getUIManager(reactContext, uiManagerType)
223
- .getEventDispatcher();
224
-
225
- // Set up a parent view for triggering visibility in subviews that depend on it.
226
- // Mainly ReactImageView depends on Fresco which depends on onVisibilityChanged() event
227
- attacherGroup = new ViewAttacherGroup(context);
228
- LayoutParams attacherLayoutParams = new LayoutParams(0, 0);
229
- attacherLayoutParams.width = 0;
230
- attacherLayoutParams.height = 0;
231
- attacherLayoutParams.leftMargin = 99999999;
232
- attacherLayoutParams.topMargin = 99999999;
233
- attacherGroup.setLayoutParams(attacherLayoutParams);
234
- addView(attacherGroup);
235
- }
236
-
237
- @Override
238
- public void onMapReady(@NonNull final GoogleMap map) {
239
- if (destroyed) {
240
- return;
241
- }
242
- this.map = map;
243
-
244
- markerManager = new MarkerManager(map);
245
- markerCollection = markerManager.newCollection();
246
- polylineManager = new PolylineManager(map);
247
- polylineCollection = polylineManager.newCollection();
248
- polygonManager = new PolygonManager(map);
249
- polygonCollection = polygonManager.newCollection();
250
- CircleManager circleManager = new CircleManager(map);
251
- circleCollection = circleManager.newCollection();
252
- groundOverlayManager = new GroundOverlayManager(map);
253
- groundOverlayCollection = groundOverlayManager.newCollection();
254
-
255
- markerCollection.setInfoWindowAdapter(this);
256
- markerCollection.setOnMarkerDragListener(this);
257
- this.map.setOnIndoorStateChangeListener(this);
258
-
259
- applyBridgedProps();
260
-
261
- manager.pushEvent(context, this, "onMapReady", new WritableNativeMap());
262
-
263
- final MapView view = this;
264
-
265
- map.setOnMyLocationChangeListener(new GoogleMap.OnMyLocationChangeListener() {
266
- @Override
267
- public void onMyLocationChange(Location location){
268
- WritableMap event = new WritableNativeMap();
686
+ onPause();
687
+ paused = true;
688
+ }
689
+ onDestroy();
690
+ }
269
691
 
270
- WritableMap coordinate = new WritableNativeMap();
271
- coordinate.putDouble("latitude", location.getLatitude());
272
- coordinate.putDouble("longitude", location.getLongitude());
273
- coordinate.putDouble("altitude", location.getAltitude());
274
- coordinate.putDouble("timestamp", location.getTime());
275
- coordinate.putDouble("accuracy", location.getAccuracy());
276
- coordinate.putDouble("speed", location.getSpeed());
277
- coordinate.putDouble("heading", location.getBearing());
278
- coordinate.putBoolean("isFromMockProvider", location.isFromMockProvider());
692
+ public void setInitialCameraSet(boolean initialCameraSet) {
693
+ this.initialCameraSet = initialCameraSet;
694
+ }
279
695
 
280
- event.putMap("coordinate", coordinate);
696
+ public void setInitialRegion(ReadableMap initialRegion) {
697
+ this.initialRegion = initialRegion;
698
+ // Theoretically onMapReady might be called before setInitialRegion
699
+ // In that case, trigger moveToRegion manually
700
+ if (!initialRegionSet && map != null) {
701
+ moveToRegion(initialRegion);
702
+ initialRegionSet = true;
703
+ }
704
+ }
281
705
 
282
- manager.pushEvent(context, view, "onUserLocationChange", event);
283
- }
284
- });
706
+ public void setInitialCamera(ReadableMap initialCamera) {
707
+ this.initialCamera = initialCamera;
708
+ if (!initialCameraSet && map != null) {
709
+ moveToCamera(initialCamera);
710
+ initialCameraSet = true;
711
+ }
712
+ }
285
713
 
286
- markerCollection.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
287
- @Override
288
- public boolean onMarkerClick(@NonNull Marker marker) {
289
- MapMarker airMapMarker = getMarkerMap(marker);
714
+ private void applyBridgedProps() {
715
+ if (initialRegion != null) {
716
+ moveToRegion(initialRegion);
717
+ initialRegionSet = true;
718
+ } else if (region != null) {
719
+ moveToRegion(region);
720
+ } else if (initialCamera != null) {
721
+ moveToCamera(initialCamera);
722
+ initialCameraSet = true;
723
+ } else if (camera != null) {
724
+ moveToCamera(camera);
725
+ }
726
+ if (customMapStyleString != null) {
727
+ map.setMapStyle(new MapStyleOptions(customMapStyleString));
728
+ }
729
+ this.setPoiClickEnabled(poiClickEnabled);
730
+ }
290
731
 
291
- WritableMap event = makeClickEventData(marker.getPosition());
292
- event.putString("action", "marker-press");
293
- event.putString("id", airMapMarker.getIdentifier());
294
- manager.pushEvent(context, view, "onMarkerPress", event);
732
+ public static LatLngBounds latLngBoundsFromRegion(ReadableMap region) {
733
+ if (region == null) return null;
734
+
735
+ double lng = region.getDouble("longitude");
736
+ double lat = region.getDouble("latitude");
737
+ double lngDelta = region.getDouble("longitudeDelta");
738
+ double latDelta = region.getDouble("latitudeDelta");
739
+ return new LatLngBounds(
740
+ new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest
741
+ new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast
742
+ );
743
+ }
295
744
 
296
- event = makeClickEventData(marker.getPosition());
297
- event.putString("action", "marker-press");
298
- event.putString("id", airMapMarker.getIdentifier());
299
- manager.pushEvent(context, airMapMarker, "onPress", event);
745
+ private void moveToRegion(ReadableMap region) {
746
+ LatLngBounds bounds = latLngBoundsFromRegion(region);
747
+ if (bounds == null) return;
748
+ double lng = region.getDouble("longitude");
749
+ double lat = region.getDouble("latitude");
750
+ if (super.getHeight() <= 0 || super.getWidth() <= 0) {
751
+ // in this case, our map has not been laid out yet, so we save the bounds in a local
752
+ // variable, and make a guess of zoomLevel 10. Not to worry, though: as soon as layout
753
+ // occurs, we will move the camera to the saved bounds. Note that if we tried to move
754
+ // to the bounds now, it would trigger an exception.
755
+ map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lng), 10));
756
+ boundsToMove = bounds;
757
+ } else {
758
+ map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
759
+ boundsToMove = null;
760
+ }
761
+ }
762
+
763
+ public void setRegion(ReadableMap region) {
764
+ this.region = region;
765
+ if (region != null && map != null) {
766
+ moveToRegion(region);
767
+ }
768
+ }
769
+
770
+ public void setCamera(ReadableMap camera) {
771
+ this.camera = camera;
772
+ if (camera != null && map != null) {
773
+ moveToCamera(camera);
774
+ }
775
+ }
776
+
777
+ public static CameraPosition cameraPositionFromMap(ReadableMap camera) {
778
+ if (camera == null) return null;
779
+
780
+ CameraPosition.Builder builder = new CameraPosition.Builder();
781
+
782
+ ReadableMap center = camera.getMap("center");
783
+ if (center != null) {
784
+ double lng = center.getDouble("longitude");
785
+ double lat = center.getDouble("latitude");
786
+ builder.target(new LatLng(lat, lng));
787
+ }
788
+
789
+ builder.tilt((float) camera.getDouble("pitch"));
790
+ builder.bearing((float) camera.getDouble("heading"));
791
+ builder.zoom((float) camera.getDouble("zoom"));
792
+
793
+ return builder.build();
794
+ }
300
795
 
301
- handleMarkerSelection(airMapMarker);
796
+ public CameraPosition cameraPositionFromJSON(JSONObject camera) throws JSONException {
797
+ if (camera == null) return null;
798
+ if (map == null) return null;
302
799
 
303
- // Return false to open the callout info window and center on the marker
304
- // https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap
305
- // .OnMarkerClickListener
306
- if (view.moveOnMarkerPress) {
307
- return false;
800
+ CameraPosition.Builder builder = new CameraPosition.Builder();
801
+
802
+ if (camera.has("center")) {
803
+ JSONObject center = camera.getJSONObject("center");
804
+ if (center != null) {
805
+ double lng = center.getDouble("longitude");
806
+ double lat = center.getDouble("latitude");
807
+ builder.target(new LatLng(lat, lng));
808
+ }
308
809
  } else {
309
- marker.showInfoWindow();
310
- return true;
311
- }
312
- }
313
- });
314
-
315
- polygonCollection.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() {
316
- @Override
317
- public void onPolygonClick(@NonNull Polygon polygon) {
318
- WritableMap event = makeClickEventData(tapLocation);
319
- event.putString("action", "polygon-press");
320
- manager.pushEvent(context, polygonMap.get(polygon), "onPress", event);
321
- }
322
- });
323
-
324
- polylineCollection.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() {
325
- @Override
326
- public void onPolylineClick(@NonNull Polyline polyline) {
327
- WritableMap event = makeClickEventData(tapLocation);
328
- event.putString("action", "polyline-press");
329
- manager.pushEvent(context, polylineMap.get(polyline), "onPress", event);
330
- }
331
- });
332
-
333
- markerCollection.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
334
- @Override
335
- public void onInfoWindowClick(@NonNull Marker marker) {
336
- WritableMap event = makeClickEventData(marker.getPosition());
337
- event.putString("action", "callout-press");
338
- manager.pushEvent(context, view, "onCalloutPress", event);
810
+ builder.target(map.getCameraPosition().target);
811
+ }
339
812
 
340
- event = makeClickEventData(marker.getPosition());
341
- event.putString("action", "callout-press");
342
- MapMarker markerView = getMarkerMap(marker);
343
- manager.pushEvent(context, markerView, "onCalloutPress", event);
813
+ if (camera.has("pitch")) {
814
+ builder.tilt((float) camera.getDouble("pitch"));
815
+ } else {
816
+ builder.tilt(map.getCameraPosition().tilt);
817
+ }
818
+ if (camera.has("heading")) {
819
+ builder.bearing((float) camera.getDouble("heading"));
820
+ } else {
821
+ builder.bearing(map.getCameraPosition().bearing);
822
+ }
823
+ if (camera.has("zoom")) {
824
+ builder.zoom((float) camera.getDouble("zoom"));
825
+ } else {
826
+ builder.zoom(map.getCameraPosition().zoom);
827
+ }
344
828
 
345
- event = makeClickEventData(marker.getPosition());
346
- event.putString("action", "callout-press");
347
- MapCallout infoWindow = markerView.getCalloutView();
348
- if (infoWindow != null) manager.pushEvent(context, infoWindow, "onPress", event);
349
- }
350
- });
351
-
352
- map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
353
- @Override
354
- public void onMapClick(@NonNull LatLng point) {
355
- WritableMap event = makeClickEventData(point);
356
- event.putString("action", "press");
357
- manager.pushEvent(context, view, "onPress", event);
358
-
359
- handleMarkerSelection(null);
360
- }
361
- });
362
-
363
- map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
364
- @Override
365
- public void onMapLongClick(@NonNull LatLng point) {
366
- WritableMap event = makeClickEventData(point);
367
- event.putString("action", "long-press");
368
- manager.pushEvent(context, view, "onLongPress", makeClickEventData(point));
369
- }
370
- });
371
-
372
- groundOverlayCollection.setOnGroundOverlayClickListener(new GoogleMap.OnGroundOverlayClickListener() {
373
- @Override
374
- public void onGroundOverlayClick(@NonNull GroundOverlay groundOverlay) {
375
- WritableMap event = makeClickEventData(groundOverlay.getPosition());
376
- event.putString("action", "overlay-press");
377
- manager.pushEvent(context, overlayMap.get(groundOverlay), "onPress", event);
378
- }
379
- });
380
-
381
- map.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
382
- @Override
383
- public void onCameraMoveStarted(int reason) {
384
- cameraMoveReason = reason;
385
- boolean isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == reason;
386
- WritableMap event = new WritableNativeMap();
387
- event.putBoolean("isGesture", isGesture);
388
- manager.pushEvent(context, view, "onRegionChangeStart", event);
389
- }
390
- });
391
-
392
- map.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
393
- @Override
394
- public void onCameraMove() {
395
- LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
829
+ return builder.build();
830
+ }
396
831
 
397
- cameraLastIdleBounds = null;
398
- boolean isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == cameraMoveReason;
832
+ public void moveToCamera(ReadableMap cameraMap) {
833
+ moveToCamera(cameraPositionFromMap(cameraMap));
834
+ }
399
835
 
400
- RegionChangeEvent event = new RegionChangeEvent(getId(), bounds, true, isGesture);
401
- eventDispatcher.dispatchEvent(event);
402
- }
403
- });
836
+ public void moveToCamera(CameraPosition camera) {
837
+ if (camera == null) return;
838
+ CameraUpdate update = CameraUpdateFactory.newCameraPosition(camera);
404
839
 
405
- map.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
406
- @Override
407
- public void onCameraIdle() {
408
- LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
409
- if ((cameraMoveReason != 0) &&
410
- ((cameraLastIdleBounds == null) ||
411
- LatLngBoundsUtils.BoundsAreDifferent(bounds, cameraLastIdleBounds))) {
412
-
413
- cameraLastIdleBounds = bounds;
414
- boolean isGesture = GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE == cameraMoveReason;
415
-
416
- RegionChangeEvent event = new RegionChangeEvent(getId(), bounds, false, isGesture);
417
- eventDispatcher.dispatchEvent(event);
418
- }
419
- }
420
- });
421
-
422
- map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
423
- @Override public void onMapLoaded() {
424
- isMapLoaded = true;
425
- manager.pushEvent(context, view, "onMapLoaded", new WritableNativeMap());
426
- MapView.this.cacheView();
427
- }
428
- });
429
-
430
- // We need to be sure to disable location-tracking when app enters background, in-case some
431
- // other module
432
- // has acquired a wake-lock and is controlling location-updates, otherwise, location-manager
433
- // will be left
434
- // updating location constantly, killing the battery, even though some other location-mgmt
435
- // module may
436
- // desire to shut-down location-services.
437
- lifecycleListener = new LifecycleEventListener() {
438
- @Override
439
- public void onHostResume() {
440
- if (hasPermissions() && map != null) {
441
- //noinspection MissingPermission
442
- map.setMyLocationEnabled(showUserLocation);
443
- map.setLocationSource(fusedLocationSource);
840
+ if (super.getHeight() <= 0 || super.getWidth() <= 0) {
841
+ // in this case, our map has not been laid out yet, so we save the camera update in a
842
+ // local variable. As soon as layout occurs, we will move the camera to the saved update.
843
+ // Note that if we tried to move to the camera now, it would trigger an exception.
844
+ cameraToSet = update;
845
+ } else {
846
+ map.moveCamera(update);
847
+ cameraToSet = null;
444
848
  }
445
- synchronized (MapView.this) {
446
- if (!destroyed) {
447
- MapView.this.onResume();
448
- }
449
- paused = false;
849
+ }
850
+
851
+ public void setMapStyle(@Nullable String customMapStyleString) {
852
+ this.customMapStyleString = customMapStyleString;
853
+ if (map != null && customMapStyleString != null) {
854
+ map.setMapStyle(new MapStyleOptions(customMapStyleString));
450
855
  }
451
- }
856
+ }
452
857
 
453
- @Override
454
- public void onHostPause() {
455
- if (hasPermissions() && map != null) {
456
- //noinspection MissingPermission
457
- map.setMyLocationEnabled(false);
858
+ public void setShowsUserLocation(boolean showUserLocation) {
859
+ this.showUserLocation = showUserLocation; // hold onto this for lifecycle handling
860
+ if (hasPermissions()) {
861
+ map.setLocationSource(fusedLocationSource);
862
+ //noinspection MissingPermission
863
+ map.setMyLocationEnabled(showUserLocation);
458
864
  }
459
- synchronized (MapView.this) {
460
- if (!destroyed) {
461
- MapView.this.onPause();
462
- }
463
- paused = true;
865
+ }
866
+
867
+ public void setUserLocationPriority(int priority) {
868
+ fusedLocationSource.setPriority(priority);
869
+ }
870
+
871
+ public void setUserLocationUpdateInterval(int interval) {
872
+ fusedLocationSource.setInterval(interval);
873
+ }
874
+
875
+ public void setUserLocationFastestInterval(int interval) {
876
+ fusedLocationSource.setFastestInterval(interval);
877
+ }
878
+
879
+ public void setShowsMyLocationButton(boolean showMyLocationButton) {
880
+ if (map != null) {
881
+ if (hasPermissions() || !showMyLocationButton) {
882
+ map.getUiSettings().setMyLocationButtonEnabled(showMyLocationButton);
883
+ }
464
884
  }
465
- }
885
+ }
466
886
 
467
- @Override
468
- public void onHostDestroy() {
469
- MapView.this.doDestroy();
470
- }
471
- };
887
+ public void setToolbarEnabled(boolean toolbarEnabled) {
888
+ if (map != null) {
889
+ if (hasPermissions() || !toolbarEnabled) {
890
+ map.getUiSettings().setMapToolbarEnabled(toolbarEnabled);
891
+ }
892
+ }
893
+ }
472
894
 
473
- context.addLifecycleEventListener(lifecycleListener);
474
- }
895
+ public void setMapType(int mapType) {
896
+ if (map != null) {
897
+ map.setMapType(mapType);
898
+ }
899
+ }
475
900
 
476
- private synchronized void handleMarkerSelection(MapMarker target) {
477
- if (selectedMarker == target) {
478
- return;
479
- }
480
-
481
- WritableMap event;
482
-
483
- if (selectedMarker != null) {
484
- event = makeClickEventData(selectedMarker.getPosition());
485
- event.putString("action", "marker-deselect");
486
- event.putString("id", selectedMarker.getIdentifier());
487
- manager.pushEvent(context, selectedMarker, "onDeselect", event);
488
-
489
- event = makeClickEventData(selectedMarker.getPosition());
490
- event.putString("action", "marker-deselect");
491
- event.putString("id", selectedMarker.getIdentifier());
492
- manager.pushEvent(context, this, "onMarkerDeselect", event);
493
- }
494
-
495
- if (target != null) {
496
- event = makeClickEventData(target.getPosition());
497
- event.putString("action", "marker-select");
498
- event.putString("id", target.getIdentifier());
499
- manager.pushEvent(context, target, "onSelect", event);
500
-
501
- event = makeClickEventData(target.getPosition());
502
- event.putString("action", "marker-select");
503
- event.putString("id", target.getIdentifier());
504
- manager.pushEvent(context, this, "onMarkerSelect", event);
505
- }
506
-
507
- selectedMarker = target;
508
- }
509
-
510
- private boolean hasPermissions() {
511
- return checkSelfPermission(getContext(), PERMISSIONS[0]) == PermissionChecker.PERMISSION_GRANTED ||
512
- checkSelfPermission(getContext(), PERMISSIONS[1]) == PermissionChecker.PERMISSION_GRANTED;
513
- }
514
-
515
-
516
- /*
517
- onDestroy is final method so I can't override it.
518
- */
519
- public synchronized void doDestroy() {
520
- if (destroyed) {
521
- return;
522
- }
523
- destroyed = true;
524
-
525
- if (lifecycleListener != null && context != null) {
526
- context.removeLifecycleEventListener(lifecycleListener);
527
- lifecycleListener = null;
528
- }
529
- if (!paused) {
530
- onPause();
531
- paused = true;
532
- }
533
- onDestroy();
534
- }
535
-
536
- public void setInitialRegion(ReadableMap initialRegion) {
537
- this.initialRegion = initialRegion;
538
- // Theoretically onMapReady might be called before setInitialRegion
539
- // In that case, trigger moveToRegion manually
540
- if (!initialRegionSet && map != null) {
541
- moveToRegion(initialRegion);
542
- initialRegionSet = true;
543
- }
544
- }
545
-
546
- public void setInitialCamera(ReadableMap initialCamera) {
547
- this.initialCamera = initialCamera;
548
- if (!initialCameraSet && map != null) {
549
- moveToCamera(initialCamera);
550
- initialCameraSet = true;
551
- }
552
- }
553
-
554
- private void applyBridgedProps() {
555
- if(initialRegion != null) {
556
- moveToRegion(initialRegion);
557
- initialRegionSet = true;
558
- } else if(region != null) {
559
- moveToRegion(region);
560
- } else if (initialCamera != null) {
561
- moveToCamera(initialCamera);
562
- initialCameraSet = true;
563
- } else if (camera != null) {
564
- moveToCamera(camera);
565
- }
566
- if(customMapStyleString != null) {
567
- map.setMapStyle(new MapStyleOptions(customMapStyleString));
568
- }
569
- this.setPoiClickEnabled(poiClickEnabled);
570
- }
571
-
572
- private void moveToRegion(ReadableMap region) {
573
- if (region == null) return;
574
-
575
- double lng = region.getDouble("longitude");
576
- double lat = region.getDouble("latitude");
577
- double lngDelta = region.getDouble("longitudeDelta");
578
- double latDelta = region.getDouble("latitudeDelta");
579
- LatLngBounds bounds = new LatLngBounds(
580
- new LatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest
581
- new LatLng(lat + latDelta / 2, lng + lngDelta / 2) // northeast
582
- );
583
- if (super.getHeight() <= 0 || super.getWidth() <= 0) {
584
- // in this case, our map has not been laid out yet, so we save the bounds in a local
585
- // variable, and make a guess of zoomLevel 10. Not to worry, though: as soon as layout
586
- // occurs, we will move the camera to the saved bounds. Note that if we tried to move
587
- // to the bounds now, it would trigger an exception.
588
- map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lng), 10));
589
- boundsToMove = bounds;
590
- } else {
591
- map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
592
- boundsToMove = null;
593
- }
594
- }
595
-
596
- public void setRegion(ReadableMap region) {
597
- this.region = region;
598
- if(region != null && map != null) {
599
- moveToRegion(region);
600
- }
601
- }
602
-
603
- public void setCamera(ReadableMap camera) {
604
- this.camera = camera;
605
- if(camera != null && map != null) {
606
- moveToCamera(camera);
607
- }
608
- }
609
- public static CameraPosition cameraPositionFromMap(ReadableMap camera){
610
- if (camera == null) return null;
611
-
612
- CameraPosition.Builder builder = new CameraPosition.Builder();
613
-
614
- ReadableMap center = camera.getMap("center");
615
- if (center != null) {
616
- double lng = center.getDouble("longitude");
617
- double lat = center.getDouble("latitude");
618
- builder.target(new LatLng(lat, lng));
619
- }
620
-
621
- builder.tilt((float)camera.getDouble("pitch"));
622
- builder.bearing((float)camera.getDouble("heading"));
623
- builder.zoom((float)camera.getDouble("zoom"));
624
-
625
- return builder.build();
626
- }
627
- public void moveToCamera(ReadableMap cameraMap) {
628
- CameraPosition camera = cameraPositionFromMap(cameraMap);
629
- if (camera == null) return;
630
- CameraUpdate update = CameraUpdateFactory.newCameraPosition(camera);
631
-
632
- if (super.getHeight() <= 0 || super.getWidth() <= 0) {
633
- // in this case, our map has not been laid out yet, so we save the camera update in a
634
- // local variable. As soon as layout occurs, we will move the camera to the saved update.
635
- // Note that if we tried to move to the camera now, it would trigger an exception.
636
- cameraToSet = update;
637
- } else {
638
- map.moveCamera(update);
639
- cameraToSet = null;
640
- }
641
- }
642
-
643
- public void setMapStyle(@Nullable String customMapStyleString) {
644
- this.customMapStyleString = customMapStyleString;
645
- if(map != null && customMapStyleString != null) {
646
- map.setMapStyle(new MapStyleOptions(customMapStyleString));
647
- }
648
- }
649
-
650
- public void setShowsUserLocation(boolean showUserLocation) {
651
- this.showUserLocation = showUserLocation; // hold onto this for lifecycle handling
652
- if (hasPermissions()) {
653
- map.setLocationSource(fusedLocationSource);
654
- //noinspection MissingPermission
655
- map.setMyLocationEnabled(showUserLocation);
656
- }
657
- }
658
-
659
- public void setUserLocationPriority(int priority){
660
- fusedLocationSource.setPriority(priority);
661
- }
662
-
663
- public void setUserLocationUpdateInterval(int interval){
664
- fusedLocationSource.setInterval(interval);
665
- }
666
-
667
- public void setUserLocationFastestInterval(int interval){
668
- fusedLocationSource.setFastestInterval(interval);
669
- }
670
-
671
- public void setShowsMyLocationButton(boolean showMyLocationButton) {
672
- if (hasPermissions() || !showMyLocationButton) {
673
- map.getUiSettings().setMyLocationButtonEnabled(showMyLocationButton);
674
- }
675
- }
676
-
677
- public void setToolbarEnabled(boolean toolbarEnabled) {
678
- if (hasPermissions() || !toolbarEnabled) {
679
- map.getUiSettings().setMapToolbarEnabled(toolbarEnabled);
680
- }
681
- }
682
-
683
- public void setCacheEnabled(boolean cacheEnabled) {
684
- this.cacheEnabled = cacheEnabled;
685
- this.cacheView();
686
- }
687
-
688
- public void setPoiClickEnabled(boolean poiClickEnabled) {
689
- this.poiClickEnabled = poiClickEnabled;
690
- map.setOnPoiClickListener(poiClickEnabled ? this : null);
691
- }
692
-
693
- public void enableMapLoading(boolean loadingEnabled) {
694
- if (loadingEnabled && !this.isMapLoaded) {
695
- this.getMapLoadingLayoutView().setVisibility(View.VISIBLE);
696
- }
697
- }
698
-
699
- public void setMoveOnMarkerPress(boolean moveOnPress) {
700
- this.moveOnMarkerPress = moveOnPress;
701
- }
702
-
703
- public void setLoadingBackgroundColor(Integer loadingBackgroundColor) {
704
- this.loadingBackgroundColor = loadingBackgroundColor;
705
-
706
- if (this.mapLoadingLayout != null) {
707
- if (loadingBackgroundColor == null) {
708
- this.mapLoadingLayout.setBackgroundColor(Color.WHITE);
709
- } else {
710
- this.mapLoadingLayout.setBackgroundColor(this.loadingBackgroundColor);
711
- }
712
- }
713
- }
714
-
715
- public void setLoadingIndicatorColor(Integer loadingIndicatorColor) {
716
- this.loadingIndicatorColor = loadingIndicatorColor;
717
- if (this.mapLoadingProgressBar != null) {
718
- Integer color = loadingIndicatorColor;
719
- if (color == null) {
720
- color = Color.parseColor("#606060");
721
- }
722
-
723
- ColorStateList progressTintList = ColorStateList.valueOf(loadingIndicatorColor);
724
- ColorStateList secondaryProgressTintList = ColorStateList.valueOf(loadingIndicatorColor);
725
- ColorStateList indeterminateTintList = ColorStateList.valueOf(loadingIndicatorColor);
726
-
727
- this.mapLoadingProgressBar.setProgressTintList(progressTintList);
728
- this.mapLoadingProgressBar.setSecondaryProgressTintList(secondaryProgressTintList);
729
- this.mapLoadingProgressBar.setIndeterminateTintList(indeterminateTintList);
730
- }
731
- }
732
-
733
- public void setHandlePanDrag(boolean handlePanDrag) {
734
- this.handlePanDrag = handlePanDrag;
735
- }
736
-
737
- public void addFeature(View child, int index) {
738
- // Our desired API is to pass up annotations/overlays as children to the mapview component.
739
- // This is where we intercept them and do the appropriate underlying mapview action.
740
- if (child instanceof MapMarker) {
741
- MapMarker annotation = (MapMarker) child;
742
- annotation.addToMap(markerCollection);
743
- features.add(index, annotation);
744
-
745
- // Allow visibility event to be triggered later
746
- int visibility = annotation.getVisibility();
747
- annotation.setVisibility(INVISIBLE);
748
-
749
- // Remove from a view group if already present, prevent "specified child
750
- // already had a parent" error.
751
- ViewGroup annotationParent = (ViewGroup)annotation.getParent();
752
- if (annotationParent != null) {
753
- annotationParent.removeView(annotation);
754
- }
755
-
756
- // Add to the parent group
757
- attacherGroup.addView(annotation);
758
-
759
- // Trigger visibility event if necessary.
760
- // With some testing, seems like it is not always
761
- // triggered just by being added to a parent view.
762
- annotation.setVisibility(visibility);
763
-
764
- Marker marker = (Marker) annotation.getFeature();
765
- markerMap.put(marker, annotation);
766
- } else if (child instanceof MapPolyline) {
767
- MapPolyline polylineView = (MapPolyline) child;
768
- polylineView.addToMap(polylineCollection);
769
- features.add(index, polylineView);
770
- Polyline polyline = (Polyline) polylineView.getFeature();
771
- polylineMap.put(polyline, polylineView);
772
- } else if (child instanceof MapGradientPolyline) {
773
- MapGradientPolyline polylineView = (MapGradientPolyline) child;
774
- polylineView.addToMap(map);
775
- features.add(index, polylineView);
776
- TileOverlay tileOverlay = (TileOverlay) polylineView.getFeature();
777
- gradientPolylineMap.put(tileOverlay, polylineView);
778
- } else if (child instanceof MapPolygon) {
779
- MapPolygon polygonView = (MapPolygon) child;
780
- polygonView.addToMap(polygonCollection);
781
- features.add(index, polygonView);
782
- Polygon polygon = (Polygon) polygonView.getFeature();
783
- polygonMap.put(polygon, polygonView);
784
- } else if (child instanceof MapCircle) {
785
- MapCircle circleView = (MapCircle) child;
786
- circleView.addToMap(circleCollection);
787
- features.add(index, circleView);
788
- } else if (child instanceof MapUrlTile) {
789
- MapUrlTile urlTileView = (MapUrlTile) child;
790
- urlTileView.addToMap(map);
791
- features.add(index, urlTileView);
792
- } else if (child instanceof MapWMSTile) {
793
- MapWMSTile urlTileView = (MapWMSTile) child;
794
- urlTileView.addToMap(map);
795
- features.add(index, urlTileView);
796
- } else if (child instanceof MapLocalTile) {
797
- MapLocalTile localTileView = (MapLocalTile) child;
798
- localTileView.addToMap(map);
799
- features.add(index, localTileView);
800
- } else if (child instanceof MapOverlay) {
801
- MapOverlay overlayView = (MapOverlay) child;
802
- overlayView.addToMap(groundOverlayCollection);
803
- features.add(index, overlayView);
804
- GroundOverlay overlay = (GroundOverlay) overlayView.getFeature();
805
- overlayMap.put(overlay, overlayView);
806
- } else if (child instanceof MapHeatmap) {
807
- MapHeatmap heatmapView = (MapHeatmap) child;
808
- heatmapView.addToMap(map);
809
- features.add(index, heatmapView);
810
- TileOverlay heatmap = (TileOverlay)heatmapView.getFeature();
811
- heatmapMap.put(heatmap, heatmapView);
812
- } else if (child instanceof ViewGroup) {
813
- ViewGroup children = (ViewGroup) child;
814
- for (int i = 0; i < children.getChildCount(); i++) {
815
- addFeature(children.getChildAt(i), index);
816
- }
817
- } else {
818
- addView(child, index);
819
- }
820
- }
821
-
822
- public int getFeatureCount() {
823
- return features.size();
824
- }
825
-
826
- public View getFeatureAt(int index) {
827
- return features.get(index);
828
- }
829
-
830
- public void removeFeatureAt(int index) {
831
- MapFeature feature = features.remove(index);
832
- if (feature instanceof MapMarker) {
833
- markerMap.remove(feature.getFeature());
834
- feature.removeFromMap(markerCollection);
835
- attacherGroup.removeView(feature);
836
- } else if (feature instanceof MapHeatmap) {
837
- heatmapMap.remove(feature.getFeature());
838
- feature.removeFromMap(map);
839
- } else if(feature instanceof MapCircle) {
840
- feature.removeFromMap(circleCollection);
841
- } else if(feature instanceof MapOverlay) {
842
- feature.removeFromMap(groundOverlayCollection);
843
- } else if(feature instanceof MapPolygon) {
844
- feature.removeFromMap(polygonCollection);
845
- } else if(feature instanceof MapPolyline) {
846
- feature.removeFromMap(polylineCollection);
847
- } else {
848
- feature.removeFromMap(map);
849
- }
850
- }
851
-
852
- public WritableMap makeClickEventData(LatLng point) {
853
- WritableMap event = new WritableNativeMap();
854
-
855
- WritableMap coordinate = new WritableNativeMap();
856
- coordinate.putDouble("latitude", point.latitude);
857
- coordinate.putDouble("longitude", point.longitude);
858
- event.putMap("coordinate", coordinate);
859
-
860
- Projection projection = map.getProjection();
861
- Point screenPoint = projection.toScreenLocation(point);
862
-
863
- WritableMap position = new WritableNativeMap();
864
- position.putDouble("x", screenPoint.x);
865
- position.putDouble("y", screenPoint.y);
866
- event.putMap("position", position);
867
-
868
- return event;
869
- }
870
-
871
- public void updateExtraData(Object extraData) {
872
- if (setPaddingDeferred && super.getHeight() > 0 && super.getWidth() > 0) {
873
- CameraUpdate cu = CameraUpdateFactory.newCameraPosition(map.getCameraPosition());
874
-
875
- map.setPadding(edgeLeftPadding + baseLeftMapPadding,
876
- edgeTopPadding + baseTopMapPadding,
877
- edgeRightPadding + baseRightMapPadding,
878
- edgeBottomPadding + baseBottomMapPadding);
879
- map.moveCamera(cu);
880
-
881
- // Move the google logo to the default base padding value.
882
- map.setPadding(baseLeftMapPadding, baseTopMapPadding, baseRightMapPadding, baseBottomMapPadding);
883
-
884
- setPaddingDeferred = false;
885
- }
886
-
887
- // if boundsToMove is not null, we now have the MapView's width/height, so we can apply
888
- // a proper camera move
889
- if (boundsToMove != null) {
890
- HashMap<String, Float> data = (HashMap<String, Float>) extraData;
891
- int width = data.get("width") == null ? 0 : data.get("width").intValue();
892
- int height = data.get("height") == null ? 0 : data.get("height").intValue();
893
-
894
- //fix for https://github.com/react-native-maps/react-native-maps/issues/245,
895
- //it's not guaranteed the passed-in height and width would be greater than 0.
896
- if (width <= 0 || height <= 0) {
897
- map.moveCamera(CameraUpdateFactory.newLatLngBounds(boundsToMove, 0));
898
- } else {
899
- map.moveCamera(CameraUpdateFactory.newLatLngBounds(boundsToMove, width, height, 0));
900
- }
901
-
902
- boundsToMove = null;
903
- cameraToSet = null;
904
- }
905
- else if (cameraToSet != null) {
906
- map.moveCamera(cameraToSet);
907
- cameraToSet = null;
908
- }
909
- }
910
-
911
- public void animateToCamera(ReadableMap camera, int duration) {
912
- if (map == null) return;
913
- CameraPosition.Builder builder = new CameraPosition.Builder(map.getCameraPosition());
914
- if (camera.hasKey("zoom")) {
915
- builder.zoom((float)camera.getDouble("zoom"));
916
- }
917
- if (camera.hasKey("heading")) {
918
- builder.bearing((float)camera.getDouble("heading"));
901
+ public void setCacheEnabled(boolean cacheEnabled) {
902
+ this.cacheEnabled = cacheEnabled;
903
+ this.cacheView();
919
904
  }
920
- if (camera.hasKey("pitch")) {
921
- builder.tilt((float)camera.getDouble("pitch"));
922
- }
923
- if (camera.hasKey("center")) {
924
- ReadableMap center = camera.getMap("center");
925
- builder.target(new LatLng(center.getDouble("latitude"), center.getDouble("longitude")));
926
- }
927
-
928
- CameraUpdate update = CameraUpdateFactory.newCameraPosition(builder.build());
929
-
930
- if (duration <= 0) {
931
- map.moveCamera(update);
932
- }
933
- else {
934
- map.animateCamera(update, duration, null);
905
+
906
+ public void setPoiClickEnabled(boolean poiClickEnabled) {
907
+ this.poiClickEnabled = poiClickEnabled;
908
+ if (map != null) {
909
+ map.setOnPoiClickListener(poiClickEnabled ? this : null);
910
+ }
935
911
  }
936
- }
937
912
 
938
- public void animateToRegion(LatLngBounds bounds, int duration) {
939
- if (map == null) return;
940
- if(duration <= 0) {
941
- map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
942
- } else {
943
- map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null);
913
+ public void setLoadingEnabled(boolean loadingEnabled) {
914
+ if (loadingEnabled && !this.isMapLoaded) {
915
+ this.getMapLoadingLayoutView().setVisibility(View.VISIBLE);
916
+ }
944
917
  }
945
- }
946
918
 
947
- public void fitToElements(ReadableMap edgePadding, boolean animated) {
948
- if (map == null) return;
919
+ public void setMoveOnMarkerPress(boolean moveOnPress) {
920
+ this.moveOnMarkerPress = moveOnPress;
921
+ }
949
922
 
950
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
923
+ public void setMaxZoomLevel(float maxZoomLevel) {
924
+ this.maxZoomLevel = maxZoomLevel;
925
+ if (map != null) {
926
+ map.setMaxZoomPreference(maxZoomLevel);
927
+ }
928
+ }
951
929
 
952
- boolean addedPosition = false;
930
+ public void setMinZoomLevel(float minZoomLevel) {
931
+ this.minZoomLevel = minZoomLevel;
932
+ if (map != null) {
933
+ map.setMinZoomPreference(minZoomLevel);
934
+ }
935
+ }
953
936
 
954
- for (MapFeature feature : features) {
955
- if (feature instanceof MapMarker) {
956
- Marker marker = (Marker) feature.getFeature();
957
- builder.include(marker.getPosition());
958
- addedPosition = true;
959
- }
960
- // TODO(lmr): may want to include shapes / etc.
937
+ public void setPitchEnabled(boolean pitchEnabled) {
938
+ this.pitchEnabled = pitchEnabled;
939
+ if (map != null) {
940
+ map.getUiSettings().setTiltGesturesEnabled(pitchEnabled);
941
+ }
961
942
  }
962
- if (addedPosition) {
963
- LatLngBounds bounds = builder.build();
964
- CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
965
943
 
966
- if (edgePadding != null) {
967
- appendMapPadding(edgePadding.getInt("left"), edgePadding.getInt("top"),
968
- edgePadding.getInt("right"), edgePadding.getInt("bottom"));
969
- }
944
+ public void setShowsCompass(boolean showsCompass) {
945
+ this.showsCompass = showsCompass;
946
+ if (map != null) {
947
+ map.getUiSettings().setCompassEnabled(showsCompass);
948
+ }
949
+ }
970
950
 
971
- if (animated) {
972
- map.animateCamera(cu);
973
- } else {
974
- map.moveCamera(cu);
975
- }
976
- // Move the google logo to the default base padding value.
977
- map.setPadding(baseLeftMapPadding, baseTopMapPadding, baseRightMapPadding, baseBottomMapPadding);
951
+ public void setRotateEnabled(boolean rotateEnabled) {
952
+ this.rotateEnabled = rotateEnabled;
953
+ if (map != null) {
954
+ map.getUiSettings().setRotateGesturesEnabled(rotateEnabled);
955
+ }
956
+ }
957
+
958
+ public void setZoomEnabled(boolean zoomEnabled) {
959
+ this.zoomEnabled = zoomEnabled;
960
+ if (map != null) {
961
+ map.getUiSettings().setZoomGesturesEnabled(zoomEnabled);
962
+ }
963
+ }
964
+
965
+ public void setZoomControlEnabled(boolean zoomControlEnabled) {
966
+ this.zoomControlEnabled = zoomControlEnabled;
967
+ if (map != null) {
968
+ map.getUiSettings().setZoomControlsEnabled(zoomControlEnabled);
969
+ }
970
+ }
971
+
972
+ public void setScrollDuringRotateOrZoomEnabled(boolean scrollDuringRotateOrZoomEnabled) {
973
+ this.scrollDuringRotateOrZoomEnabled = scrollDuringRotateOrZoomEnabled;
974
+ if (map != null) {
975
+ map.getUiSettings().setScrollGesturesEnabledDuringRotateOrZoom(scrollDuringRotateOrZoomEnabled);
976
+ }
977
+ }
978
+
979
+ public void setScrollEnabled(boolean scrollEnabled) {
980
+ this.scrollEnabled = scrollEnabled;
981
+ if (map != null) {
982
+ map.getUiSettings().setScrollGesturesEnabled(scrollEnabled);
983
+ }
984
+ }
985
+
986
+ public void setShowIndoors(boolean showIndoors) {
987
+ this.showIndoors = showIndoors;
988
+ if (map != null) {
989
+ map.setIndoorEnabled(showIndoors);
990
+ }
991
+ }
992
+
993
+ public void setShowsIndoorLevelPicker(boolean showsIndoorLevelPicker) {
994
+ this.showsIndoorLevelPicker = showsIndoorLevelPicker;
995
+ if (map != null) {
996
+ map.getUiSettings().setIndoorLevelPickerEnabled(showsIndoorLevelPicker);
997
+ }
998
+ }
999
+
1000
+ public void setShowBuildings(boolean showBuildings) {
1001
+ this.setShowBuildings = showBuildings;
1002
+ if (map != null) {
1003
+ map.setBuildingsEnabled(showBuildings);
1004
+ }
1005
+ }
1006
+
1007
+
1008
+ public void setLoadingBackgroundColor(Integer loadingBackgroundColor) {
1009
+ this.loadingBackgroundColor = loadingBackgroundColor;
1010
+
1011
+ if (this.mapLoadingLayout != null) {
1012
+ if (loadingBackgroundColor == null) {
1013
+ this.mapLoadingLayout.setBackgroundColor(Color.WHITE);
1014
+ } else {
1015
+ this.mapLoadingLayout.setBackgroundColor(this.loadingBackgroundColor);
1016
+ }
1017
+ }
1018
+ }
1019
+
1020
+ public void setLoadingIndicatorColor(Integer loadingIndicatorColor) {
1021
+ this.loadingIndicatorColor = loadingIndicatorColor;
1022
+ if (this.mapLoadingProgressBar != null) {
1023
+ Integer color = loadingIndicatorColor;
1024
+ if (color == null) {
1025
+ color = Color.parseColor("#606060");
1026
+ }
1027
+
1028
+ ColorStateList progressTintList = ColorStateList.valueOf(loadingIndicatorColor);
1029
+ ColorStateList secondaryProgressTintList = ColorStateList.valueOf(loadingIndicatorColor);
1030
+ ColorStateList indeterminateTintList = ColorStateList.valueOf(loadingIndicatorColor);
1031
+
1032
+ this.mapLoadingProgressBar.setProgressTintList(progressTintList);
1033
+ this.mapLoadingProgressBar.setSecondaryProgressTintList(secondaryProgressTintList);
1034
+ this.mapLoadingProgressBar.setIndeterminateTintList(indeterminateTintList);
1035
+ }
1036
+ }
1037
+
1038
+ public void setHandlePanDrag(boolean handlePanDrag) {
1039
+ this.handlePanDrag = handlePanDrag;
1040
+ }
1041
+
1042
+ public void addFeature(View child, int index) {
1043
+ // Our desired API is to pass up annotations/overlays as children to the mapview component.
1044
+ // This is where we intercept them and do the appropriate underlying mapview action.
1045
+ if (child instanceof MapMarker) {
1046
+ MapMarker annotation = (MapMarker) child;
1047
+ annotation.addToMap(markerCollection);
1048
+ features.add(index, annotation);
1049
+
1050
+ // Allow visibility event to be triggered later
1051
+ int visibility = annotation.getVisibility();
1052
+ annotation.setVisibility(INVISIBLE);
1053
+
1054
+ // Remove from a view group if already present, prevent "specified child
1055
+ // already had a parent" error.
1056
+ ViewGroup annotationParent = (ViewGroup) annotation.getParent();
1057
+ if (annotationParent != null) {
1058
+ annotationParent.removeView(annotation);
1059
+ }
1060
+
1061
+ // Add to the parent group
1062
+ attacherGroup.addView(annotation);
1063
+
1064
+ // Trigger visibility event if necessary.
1065
+ // With some testing, seems like it is not always
1066
+ // triggered just by being added to a parent view.
1067
+ annotation.setVisibility(visibility);
1068
+
1069
+ Marker marker = (Marker) annotation.getFeature();
1070
+ markerMap.put(marker, annotation);
1071
+ } else if (child instanceof MapPolyline) {
1072
+ MapPolyline polylineView = (MapPolyline) child;
1073
+ polylineView.addToMap(polylineCollection);
1074
+ features.add(index, polylineView);
1075
+ Polyline polyline = (Polyline) polylineView.getFeature();
1076
+ polylineMap.put(polyline, polylineView);
1077
+ } else if (child instanceof MapGradientPolyline) {
1078
+ MapGradientPolyline polylineView = (MapGradientPolyline) child;
1079
+ polylineView.addToMap(map);
1080
+ features.add(index, polylineView);
1081
+ TileOverlay tileOverlay = (TileOverlay) polylineView.getFeature();
1082
+ gradientPolylineMap.put(tileOverlay, polylineView);
1083
+ } else if (child instanceof MapPolygon) {
1084
+ MapPolygon polygonView = (MapPolygon) child;
1085
+ polygonView.addToMap(polygonCollection);
1086
+ features.add(index, polygonView);
1087
+ Polygon polygon = (Polygon) polygonView.getFeature();
1088
+ polygonMap.put(polygon, polygonView);
1089
+ } else if (child instanceof MapCircle) {
1090
+ MapCircle circleView = (MapCircle) child;
1091
+ circleView.addToMap(circleCollection);
1092
+ features.add(index, circleView);
1093
+ } else if (child instanceof MapUrlTile) {
1094
+ MapUrlTile urlTileView = (MapUrlTile) child;
1095
+ urlTileView.addToMap(map);
1096
+ features.add(index, urlTileView);
1097
+ } else if (child instanceof MapWMSTile) {
1098
+ MapWMSTile urlTileView = (MapWMSTile) child;
1099
+ urlTileView.addToMap(map);
1100
+ features.add(index, urlTileView);
1101
+ } else if (child instanceof MapLocalTile) {
1102
+ MapLocalTile localTileView = (MapLocalTile) child;
1103
+ localTileView.addToMap(map);
1104
+ features.add(index, localTileView);
1105
+ } else if (child instanceof MapOverlay) {
1106
+ MapOverlay overlayView = (MapOverlay) child;
1107
+ overlayView.addToMap(groundOverlayCollection);
1108
+ features.add(index, overlayView);
1109
+ GroundOverlay overlay = (GroundOverlay) overlayView.getFeature();
1110
+ overlayMap.put(overlay, overlayView);
1111
+ } else if (child instanceof MapHeatmap) {
1112
+ MapHeatmap heatmapView = (MapHeatmap) child;
1113
+ heatmapView.addToMap(map);
1114
+ features.add(index, heatmapView);
1115
+ TileOverlay heatmap = (TileOverlay) heatmapView.getFeature();
1116
+ heatmapMap.put(heatmap, heatmapView);
1117
+ } else if (child instanceof ViewGroup) {
1118
+ ViewGroup children = (ViewGroup) child;
1119
+ for (int i = 0; i < children.getChildCount(); i++) {
1120
+ addFeature(children.getChildAt(i), index);
1121
+ }
1122
+ } else {
1123
+ addView(child, index);
1124
+ }
1125
+ }
1126
+
1127
+ public int getFeatureCount() {
1128
+ return features.size();
1129
+ }
1130
+
1131
+ public View getFeatureAt(int index) {
1132
+ return features.get(index);
1133
+ }
1134
+
1135
+ public void removeFeatureAt(int index) {
1136
+ MapFeature feature = features.remove(index);
1137
+ if (feature instanceof MapMarker) {
1138
+ markerMap.remove(feature.getFeature());
1139
+ feature.removeFromMap(markerCollection);
1140
+ attacherGroup.removeView(feature);
1141
+ } else if (feature instanceof MapHeatmap) {
1142
+ heatmapMap.remove(feature.getFeature());
1143
+ feature.removeFromMap(map);
1144
+ } else if (feature instanceof MapCircle) {
1145
+ feature.removeFromMap(circleCollection);
1146
+ } else if (feature instanceof MapOverlay) {
1147
+ feature.removeFromMap(groundOverlayCollection);
1148
+ } else if (feature instanceof MapPolygon) {
1149
+ feature.removeFromMap(polygonCollection);
1150
+ } else if (feature instanceof MapPolyline) {
1151
+ feature.removeFromMap(polylineCollection);
1152
+ } else {
1153
+ feature.removeFromMap(map);
1154
+ }
1155
+ }
1156
+
1157
+ public WritableMap makeClickEventData(LatLng point) {
1158
+ WritableMap event = new WritableNativeMap();
1159
+
1160
+ WritableMap coordinate = new WritableNativeMap();
1161
+ coordinate.putDouble("latitude", point.latitude);
1162
+ coordinate.putDouble("longitude", point.longitude);
1163
+ event.putMap("coordinate", coordinate);
1164
+
1165
+ Projection projection = map.getProjection();
1166
+ Point screenPoint = projection.toScreenLocation(point);
1167
+
1168
+ WritableMap position = new WritableNativeMap();
1169
+ position.putDouble("x", screenPoint.x);
1170
+ position.putDouble("y", screenPoint.y);
1171
+ event.putMap("position", position);
1172
+
1173
+ return event;
978
1174
  }
979
- }
980
1175
 
981
- public void fitToSuppliedMarkers(ReadableArray markerIDsArray, ReadableMap edgePadding, boolean animated) {
982
- if (map == null) return;
1176
+ public void updateExtraData(Object extraData) {
1177
+ if (setPaddingDeferred && super.getHeight() > 0 && super.getWidth() > 0) {
1178
+ CameraUpdate cu = CameraUpdateFactory.newCameraPosition(map.getCameraPosition());
1179
+
1180
+ map.setPadding(edgeLeftPadding + baseLeftMapPadding,
1181
+ edgeTopPadding + baseTopMapPadding,
1182
+ edgeRightPadding + baseRightMapPadding,
1183
+ edgeBottomPadding + baseBottomMapPadding);
1184
+ map.moveCamera(cu);
1185
+
1186
+ // Move the google logo to the default base padding value.
1187
+ map.setPadding(baseLeftMapPadding, baseTopMapPadding, baseRightMapPadding, baseBottomMapPadding);
1188
+
1189
+ setPaddingDeferred = false;
1190
+ }
1191
+
1192
+ // if boundsToMove is not null, we now have the MapView's width/height, so we can apply
1193
+ // a proper camera move
1194
+ if (boundsToMove != null) {
1195
+ HashMap<String, Float> data = (HashMap<String, Float>) extraData;
1196
+ int width = data.get("width") == null ? 0 : data.get("width").intValue();
1197
+ int height = data.get("height") == null ? 0 : data.get("height").intValue();
1198
+
1199
+ //fix for https://github.com/react-native-maps/react-native-maps/issues/245,
1200
+ //it's not guaranteed the passed-in height and width would be greater than 0.
1201
+ if (width <= 0 || height <= 0) {
1202
+ map.moveCamera(CameraUpdateFactory.newLatLngBounds(boundsToMove, 0));
1203
+ } else {
1204
+ map.moveCamera(CameraUpdateFactory.newLatLngBounds(boundsToMove, width, height, 0));
1205
+ }
983
1206
 
984
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
1207
+ boundsToMove = null;
1208
+ cameraToSet = null;
1209
+ } else if (cameraToSet != null) {
1210
+ map.moveCamera(cameraToSet);
1211
+ cameraToSet = null;
1212
+ }
1213
+ }
1214
+ public void animateToCamera(CameraPosition position, int duration) {
1215
+ if (map == null) return;
1216
+ CameraUpdate update = CameraUpdateFactory.newCameraPosition(position);
1217
+ if (duration <= 0) {
1218
+ map.moveCamera(update);
1219
+ } else {
1220
+ map.animateCamera(update, duration, null);
1221
+ }
1222
+ }
1223
+
1224
+ public void animateToCamera(ReadableMap camera, int duration) {
1225
+ if (map == null) return;
1226
+ CameraPosition.Builder builder = new CameraPosition.Builder(map.getCameraPosition());
1227
+ if (camera.hasKey("zoom")) {
1228
+ builder.zoom((float) camera.getDouble("zoom"));
1229
+ }
1230
+ if (camera.hasKey("heading")) {
1231
+ builder.bearing((float) camera.getDouble("heading"));
1232
+ }
1233
+ if (camera.hasKey("pitch")) {
1234
+ builder.tilt((float) camera.getDouble("pitch"));
1235
+ }
1236
+ if (camera.hasKey("center")) {
1237
+ ReadableMap center = camera.getMap("center");
1238
+ builder.target(new LatLng(center.getDouble("latitude"), center.getDouble("longitude")));
1239
+ }
1240
+ animateToCamera(builder.build(), duration);
1241
+ }
985
1242
 
986
- String[] markerIDs = new String[markerIDsArray.size()];
987
- for (int i = 0; i < markerIDsArray.size(); i++) {
988
- markerIDs[i] = markerIDsArray.getString(i);
1243
+ public void animateToRegion(LatLngBounds bounds, int duration) {
1244
+ if (map == null) return;
1245
+ if (duration <= 0) {
1246
+ map.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
1247
+ } else {
1248
+ map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0), duration, null);
1249
+ }
989
1250
  }
990
1251
 
991
- boolean addedPosition = false;
1252
+ public void fitToElements(ReadableMap edgePadding, boolean animated) {
1253
+ if (map == null) return;
992
1254
 
993
- List<String> markerIDList = Arrays.asList(markerIDs);
1255
+ LatLngBounds.Builder builder = new LatLngBounds.Builder();
994
1256
 
995
- for (MapFeature feature : features) {
996
- if (feature instanceof MapMarker) {
997
- String identifier = ((MapMarker) feature).getIdentifier();
998
- Marker marker = (Marker) feature.getFeature();
999
- if (markerIDList.contains(identifier)) {
1000
- builder.include(marker.getPosition());
1001
- addedPosition = true;
1257
+ boolean addedPosition = false;
1258
+
1259
+ for (MapFeature feature : features) {
1260
+ if (feature instanceof MapMarker) {
1261
+ Marker marker = (Marker) feature.getFeature();
1262
+ builder.include(marker.getPosition());
1263
+ addedPosition = true;
1264
+ }
1265
+ // TODO(lmr): may want to include shapes / etc.
1266
+ }
1267
+ if (addedPosition) {
1268
+ LatLngBounds bounds = builder.build();
1269
+ CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
1270
+
1271
+ if (edgePadding != null) {
1272
+ appendMapPadding(edgePadding.getInt("left"), edgePadding.getInt("top"),
1273
+ edgePadding.getInt("right"), edgePadding.getInt("bottom"));
1274
+ }
1275
+
1276
+ if (animated) {
1277
+ map.animateCamera(cu);
1278
+ } else {
1279
+ map.moveCamera(cu);
1280
+ }
1281
+ // Move the google logo to the default base padding value.
1282
+ map.setPadding(baseLeftMapPadding, baseTopMapPadding, baseRightMapPadding, baseBottomMapPadding);
1002
1283
  }
1003
- }
1004
1284
  }
1005
1285
 
1006
- if (addedPosition) {
1007
- LatLngBounds bounds = builder.build();
1008
- CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
1286
+ public void fitToSuppliedMarkers(ReadableArray markerIDsArray, ReadableMap edgePadding, boolean animated) {
1287
+ if (map == null) return;
1288
+
1289
+ LatLngBounds.Builder builder = new LatLngBounds.Builder();
1009
1290
 
1010
- if (edgePadding != null) {
1011
- appendMapPadding(edgePadding.getInt("left"), edgePadding.getInt("top"),
1012
- edgePadding.getInt("right"), edgePadding.getInt("bottom"));
1013
- }
1291
+ String[] markerIDs = new String[markerIDsArray.size()];
1292
+ for (int i = 0; i < markerIDsArray.size(); i++) {
1293
+ markerIDs[i] = markerIDsArray.getString(i);
1294
+ }
1014
1295
 
1015
- if (animated) {
1016
- map.animateCamera(cu);
1017
- } else {
1296
+ boolean addedPosition = false;
1297
+
1298
+ List<String> markerIDList = Arrays.asList(markerIDs);
1299
+
1300
+ for (MapFeature feature : features) {
1301
+ if (feature instanceof MapMarker) {
1302
+ String identifier = ((MapMarker) feature).getIdentifier();
1303
+ Marker marker = (Marker) feature.getFeature();
1304
+ if (markerIDList.contains(identifier)) {
1305
+ builder.include(marker.getPosition());
1306
+ addedPosition = true;
1307
+ }
1308
+ }
1309
+ }
1310
+
1311
+ if (addedPosition) {
1312
+ LatLngBounds bounds = builder.build();
1313
+ CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
1314
+
1315
+ if (edgePadding != null) {
1316
+ appendMapPadding(edgePadding.getInt("left"), edgePadding.getInt("top"),
1317
+ edgePadding.getInt("right"), edgePadding.getInt("bottom"));
1318
+ }
1319
+
1320
+ if (animated) {
1321
+ map.animateCamera(cu);
1322
+ } else {
1323
+ map.moveCamera(cu);
1324
+ }
1325
+ // Move the google logo to the default base padding value.
1326
+ map.setPadding(baseLeftMapPadding, baseTopMapPadding, baseRightMapPadding, baseBottomMapPadding);
1327
+ }
1328
+ }
1329
+
1330
+ // padding configured by 'mapPadding' property
1331
+ int baseLeftMapPadding;
1332
+ int baseRightMapPadding;
1333
+ int baseTopMapPadding;
1334
+ int baseBottomMapPadding;
1335
+ // extra padding specified by 'edgePadding' option of fitToElements/fitToSuppliedMarkers/fitToCoordinates
1336
+ int edgeLeftPadding;
1337
+ int edgeRightPadding;
1338
+ int edgeTopPadding;
1339
+ int edgeBottomPadding;
1340
+
1341
+ public void applyBaseMapPadding(int left, int top, int right, int bottom) {
1342
+ if (super.getHeight() <= 0 || super.getWidth() <= 0) {
1343
+ // the map is not laid out yet and calling setPadding() now has no effect
1344
+ baseLeftMapPadding = left;
1345
+ baseRightMapPadding = right;
1346
+ baseTopMapPadding = top;
1347
+ baseBottomMapPadding = bottom;
1348
+ setPaddingDeferred = true;
1349
+ return;
1350
+ }
1351
+
1352
+ // retrieve current camera with current edge paddings configured
1353
+ map.setPadding(edgeLeftPadding + baseLeftMapPadding,
1354
+ edgeTopPadding + baseTopMapPadding,
1355
+ edgeRightPadding + baseRightMapPadding,
1356
+ edgeBottomPadding + baseBottomMapPadding);
1357
+ CameraUpdate cu = CameraUpdateFactory.newCameraPosition(map.getCameraPosition());
1358
+
1359
+ baseLeftMapPadding = left;
1360
+ baseRightMapPadding = right;
1361
+ baseTopMapPadding = top;
1362
+ baseBottomMapPadding = bottom;
1363
+
1364
+ // apply base paddings and restore center position of the map
1365
+ map.setPadding(edgeLeftPadding + left,
1366
+ edgeTopPadding + top,
1367
+ edgeRightPadding + right,
1368
+ edgeBottomPadding + bottom);
1018
1369
  map.moveCamera(cu);
1019
- }
1020
- // Move the google logo to the default base padding value.
1021
- map.setPadding(baseLeftMapPadding, baseTopMapPadding, baseRightMapPadding, baseBottomMapPadding);
1022
- }
1023
- }
1024
-
1025
- // padding configured by 'mapPadding' property
1026
- int baseLeftMapPadding;
1027
- int baseRightMapPadding;
1028
- int baseTopMapPadding;
1029
- int baseBottomMapPadding;
1030
- // extra padding specified by 'edgePadding' option of fitToElements/fitToSuppliedMarkers/fitToCoordinates
1031
- int edgeLeftPadding;
1032
- int edgeRightPadding;
1033
- int edgeTopPadding;
1034
- int edgeBottomPadding;
1035
-
1036
- public void applyBaseMapPadding(int left, int top, int right, int bottom){
1037
- if (super.getHeight() <= 0 || super.getWidth() <= 0) {
1038
- // the map is not laid out yet and calling setPadding() now has no effect
1039
- baseLeftMapPadding = left;
1040
- baseRightMapPadding = right;
1041
- baseTopMapPadding = top;
1042
- baseBottomMapPadding = bottom;
1043
- setPaddingDeferred = true;
1044
- return;
1045
- }
1046
-
1047
- // retrieve current camera with current edge paddings configured
1048
- map.setPadding(edgeLeftPadding + baseLeftMapPadding,
1049
- edgeTopPadding + baseTopMapPadding,
1050
- edgeRightPadding + baseRightMapPadding,
1051
- edgeBottomPadding + baseBottomMapPadding);
1052
- CameraUpdate cu = CameraUpdateFactory.newCameraPosition(map.getCameraPosition());
1053
-
1054
- baseLeftMapPadding = left;
1055
- baseRightMapPadding = right;
1056
- baseTopMapPadding = top;
1057
- baseBottomMapPadding = bottom;
1058
-
1059
- // apply base paddings and restore center position of the map
1060
- map.setPadding(edgeLeftPadding + left,
1061
- edgeTopPadding + top,
1062
- edgeRightPadding + right,
1063
- edgeBottomPadding + bottom);
1064
- map.moveCamera(cu);
1065
-
1066
- // Move the google logo to the default base padding value.
1067
- map.setPadding(left, top, right, bottom);
1068
- }
1069
-
1070
- public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePadding,
1071
- boolean animated) {
1072
- if (map == null) return;
1073
-
1074
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
1075
-
1076
- for (int i = 0; i < coordinatesArray.size(); i++) {
1077
- ReadableMap latLng = coordinatesArray.getMap(i);
1078
- double lat = latLng.getDouble("latitude");
1079
- double lng = latLng.getDouble("longitude");
1080
- builder.include(new LatLng(lat, lng));
1081
- }
1082
-
1083
- LatLngBounds bounds = builder.build();
1084
- CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
1085
-
1086
- if (edgePadding != null) {
1087
- appendMapPadding(edgePadding.getInt("left"), edgePadding.getInt("top"), edgePadding.getInt("right"), edgePadding.getInt("bottom"));
1088
- }
1089
-
1090
- if (animated) {
1091
- map.animateCamera(cu);
1092
- } else {
1093
- map.moveCamera(cu);
1094
- }
1095
- // Move the google logo to the default base padding value.
1096
- map.setPadding(baseLeftMapPadding, baseTopMapPadding, baseRightMapPadding, baseBottomMapPadding);
1097
- }
1098
-
1099
- private void appendMapPadding(int iLeft,int iTop, int iRight, int iBottom) {
1100
- double density = getResources().getDisplayMetrics().density;
1101
-
1102
- edgeLeftPadding = (int) (iLeft * density);
1103
- edgeTopPadding = (int) (iTop * density);
1104
- edgeRightPadding = (int) (iRight * density);
1105
- edgeBottomPadding = (int) (iBottom * density);
1106
-
1107
- map.setPadding(edgeLeftPadding + baseLeftMapPadding,
1108
- edgeTopPadding + baseTopMapPadding,
1109
- edgeRightPadding + baseRightMapPadding,
1110
- edgeBottomPadding + baseBottomMapPadding);
1111
- }
1112
-
1113
- public double[][] getMapBoundaries() {
1114
- LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
1115
- LatLng northEast = bounds.northeast;
1116
- LatLng southWest = bounds.southwest;
1117
-
1118
- return new double[][] {
1119
- {northEast.longitude, northEast.latitude},
1120
- {southWest.longitude, southWest.latitude}
1121
- };
1122
- }
1123
1370
 
1124
- public void setMapBoundaries(ReadableMap northEast, ReadableMap southWest) {
1125
- if (map == null) return;
1371
+ // Move the google logo to the default base padding value.
1372
+ map.setPadding(left, top, right, bottom);
1373
+ }
1374
+
1375
+ public void fitToCoordinates(ReadableArray coordinatesArray, ReadableMap edgePadding,
1376
+ boolean animated) {
1377
+ if (map == null) return;
1126
1378
 
1127
- LatLngBounds.Builder builder = new LatLngBounds.Builder();
1379
+ LatLngBounds.Builder builder = new LatLngBounds.Builder();
1128
1380
 
1129
- double latNE = northEast.getDouble("latitude");
1130
- double lngNE = northEast.getDouble("longitude");
1131
- builder.include(new LatLng(latNE, lngNE));
1381
+ for (int i = 0; i < coordinatesArray.size(); i++) {
1382
+ ReadableMap latLng = coordinatesArray.getMap(i);
1383
+ double lat = latLng.getDouble("latitude");
1384
+ double lng = latLng.getDouble("longitude");
1385
+ builder.include(new LatLng(lat, lng));
1386
+ }
1132
1387
 
1133
- double latSW = southWest.getDouble("latitude");
1134
- double lngSW = southWest.getDouble("longitude");
1135
- builder.include(new LatLng(latSW, lngSW));
1388
+ LatLngBounds bounds = builder.build();
1389
+ CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0);
1136
1390
 
1137
- LatLngBounds bounds = builder.build();
1138
-
1139
- map.setLatLngBoundsForCameraTarget(bounds);
1140
- }
1141
-
1142
- // InfoWindowAdapter interface
1143
-
1144
- @Override
1145
- public View getInfoWindow(Marker marker) {
1146
- MapMarker markerView = getMarkerMap(marker);
1147
- return markerView.getCallout();
1148
- }
1149
-
1150
- @Override
1151
- public View getInfoContents(Marker marker) {
1152
- MapMarker markerView = getMarkerMap(marker);
1153
- return markerView.getInfoContents();
1154
- }
1155
-
1156
- @Override
1157
- public boolean dispatchTouchEvent(MotionEvent ev) {
1158
- gestureDetector.onTouchEvent(ev);
1159
-
1160
- int X = (int)ev.getX();
1161
- int Y = (int)ev.getY();
1162
- if(map != null) {
1163
- tapLocation = map.getProjection().fromScreenLocation(new Point(X,Y));
1164
- }
1165
-
1166
- int action = MotionEventCompat.getActionMasked(ev);
1167
-
1168
- switch (action) {
1169
- case (MotionEvent.ACTION_DOWN):
1170
- this.getParent().requestDisallowInterceptTouchEvent(
1171
- map != null && map.getUiSettings().isScrollGesturesEnabled());
1172
- break;
1173
- case (MotionEvent.ACTION_UP):
1174
- // Clear this regardless, since isScrollGesturesEnabled() may have been updated
1175
- this.getParent().requestDisallowInterceptTouchEvent(false);
1176
- break;
1177
- }
1178
- super.dispatchTouchEvent(ev);
1179
- return true;
1180
- }
1181
-
1182
- @Override
1183
- public void onMarkerDragStart(Marker marker) {
1184
- WritableMap event = makeClickEventData(marker.getPosition());
1185
- manager.pushEvent(context, this, "onMarkerDragStart", event);
1186
-
1187
- MapMarker markerView = getMarkerMap(marker);
1188
- event = makeClickEventData(marker.getPosition());
1189
- manager.pushEvent(context, markerView, "onDragStart", event);
1190
- }
1191
-
1192
- @Override
1193
- public void onMarkerDrag(Marker marker) {
1194
- WritableMap event = makeClickEventData(marker.getPosition());
1195
- manager.pushEvent(context, this, "onMarkerDrag", event);
1196
-
1197
- MapMarker markerView = getMarkerMap(marker);
1198
- event = makeClickEventData(marker.getPosition());
1199
- manager.pushEvent(context, markerView, "onDrag", event);
1200
- }
1201
-
1202
- @Override
1203
- public void onMarkerDragEnd(Marker marker) {
1204
- WritableMap event = makeClickEventData(marker.getPosition());
1205
- manager.pushEvent(context, this, "onMarkerDragEnd", event);
1206
-
1207
- MapMarker markerView = getMarkerMap(marker);
1208
- event = makeClickEventData(marker.getPosition());
1209
- manager.pushEvent(context, markerView, "onDragEnd", event);
1210
- }
1211
-
1212
- @Override
1213
- public void onPoiClick(PointOfInterest poi) {
1214
- WritableMap event = makeClickEventData(poi.latLng);
1215
-
1216
- event.putString("placeId", poi.placeId);
1217
- event.putString("name", poi.name);
1218
-
1219
- manager.pushEvent(context, this, "onPoiClick", event);
1220
- }
1221
-
1222
- private ProgressBar getMapLoadingProgressBar() {
1223
- if (this.mapLoadingProgressBar == null) {
1224
- this.mapLoadingProgressBar = new ProgressBar(getContext());
1225
- this.mapLoadingProgressBar.setIndeterminate(true);
1226
- }
1227
- if (this.loadingIndicatorColor != null) {
1228
- this.setLoadingIndicatorColor(this.loadingIndicatorColor);
1229
- }
1230
- return this.mapLoadingProgressBar;
1231
- }
1232
-
1233
- private RelativeLayout getMapLoadingLayoutView() {
1234
- if (this.mapLoadingLayout == null) {
1235
- this.mapLoadingLayout = new RelativeLayout(getContext());
1236
- this.mapLoadingLayout.setBackgroundColor(Color.LTGRAY);
1237
- this.addView(this.mapLoadingLayout,
1238
- new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
1239
- ViewGroup.LayoutParams.MATCH_PARENT));
1240
-
1241
- RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
1242
- RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
1243
- params.addRule(RelativeLayout.CENTER_IN_PARENT);
1244
- this.mapLoadingLayout.addView(this.getMapLoadingProgressBar(), params);
1245
-
1246
- this.mapLoadingLayout.setVisibility(View.INVISIBLE);
1247
- }
1248
- this.setLoadingBackgroundColor(this.loadingBackgroundColor);
1249
- return this.mapLoadingLayout;
1250
- }
1251
-
1252
- private ImageView getCacheImageView() {
1253
- if (this.cacheImageView == null) {
1254
- this.cacheImageView = new ImageView(getContext());
1255
- this.addView(this.cacheImageView,
1256
- new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
1257
- ViewGroup.LayoutParams.MATCH_PARENT));
1258
- this.cacheImageView.setVisibility(View.INVISIBLE);
1259
- }
1260
- return this.cacheImageView;
1261
- }
1262
-
1263
- private void removeCacheImageView() {
1264
- if (this.cacheImageView != null) {
1265
- ((ViewGroup) this.cacheImageView.getParent()).removeView(this.cacheImageView);
1266
- this.cacheImageView = null;
1267
- }
1268
- }
1269
-
1270
- private void removeMapLoadingProgressBar() {
1271
- if (this.mapLoadingProgressBar != null) {
1272
- ((ViewGroup) this.mapLoadingProgressBar.getParent()).removeView(this.mapLoadingProgressBar);
1273
- this.mapLoadingProgressBar = null;
1274
- }
1275
- }
1276
-
1277
- private void removeMapLoadingLayoutView() {
1278
- this.removeMapLoadingProgressBar();
1279
- if (this.mapLoadingLayout != null) {
1280
- ((ViewGroup) this.mapLoadingLayout.getParent()).removeView(this.mapLoadingLayout);
1281
- this.mapLoadingLayout = null;
1282
- }
1283
- }
1284
-
1285
- private void cacheView() {
1286
- if (this.cacheEnabled) {
1287
- final ImageView cacheImageView = this.getCacheImageView();
1288
- final RelativeLayout mapLoadingLayout = this.getMapLoadingLayoutView();
1289
- cacheImageView.setVisibility(View.INVISIBLE);
1290
- mapLoadingLayout.setVisibility(View.VISIBLE);
1291
- if (this.isMapLoaded) {
1292
- this.map.snapshot(new GoogleMap.SnapshotReadyCallback() {
1293
- @Override public void onSnapshotReady(Bitmap bitmap) {
1294
- cacheImageView.setImageBitmap(bitmap);
1295
- cacheImageView.setVisibility(View.VISIBLE);
1296
- mapLoadingLayout.setVisibility(View.INVISIBLE);
1297
- }
1298
- });
1299
- }
1300
- } else {
1301
- this.removeCacheImageView();
1302
- if (this.isMapLoaded) {
1303
- this.removeMapLoadingLayoutView();
1304
- }
1305
- }
1306
- }
1307
-
1308
- public void onPanDrag(MotionEvent ev) {
1309
- Point point = new Point((int) ev.getX(), (int) ev.getY());
1310
- LatLng coords = this.map.getProjection().fromScreenLocation(point);
1311
- WritableMap event = makeClickEventData(coords);
1312
- manager.pushEvent(context, this, "onPanDrag", event);
1313
- }
1314
-
1315
- public void onDoublePress(MotionEvent ev) {
1316
- if (this.map == null) return;
1317
- Point point = new Point((int) ev.getX(), (int) ev.getY());
1318
- LatLng coords = this.map.getProjection().fromScreenLocation(point);
1319
- WritableMap event = makeClickEventData(coords);
1320
- manager.pushEvent(context, this, "onDoublePress", event);
1321
- }
1322
-
1323
- public void setKmlSrc(String kmlSrc) {
1324
- try {
1325
- InputStream kmlStream = new FileUtil(context).execute(kmlSrc).get();
1326
-
1327
- if (kmlStream == null) {
1328
- return;
1329
- }
1330
-
1331
- KmlLayer kmlLayer = new KmlLayer(map, kmlStream, context, markerManager, polygonManager, polylineManager, groundOverlayManager, null);
1332
- kmlLayer.addLayerToMap();
1333
-
1334
- WritableMap pointers = new WritableNativeMap();
1335
- WritableArray markers = new WritableNativeArray();
1336
-
1337
- if (kmlLayer.getContainers() == null) {
1338
- manager.pushEvent(context, this, "onKmlReady", pointers);
1339
- return;
1340
- }
1341
-
1342
- //Retrieve a nested container within the first container
1343
- KmlContainer container = kmlLayer.getContainers().iterator().next();
1344
- if (container == null || container.getContainers() == null) {
1345
- manager.pushEvent(context, this, "onKmlReady", pointers);
1346
- return;
1347
- }
1348
-
1349
-
1350
- if (container.getContainers().iterator().hasNext()) {
1351
- container = container.getContainers().iterator().next();
1352
- }
1353
-
1354
- int index = 0;
1355
- for (KmlPlacemark placemark : container.getPlacemarks()) {
1356
- MarkerOptions options = new MarkerOptions();
1357
-
1358
- if (placemark.getInlineStyle() != null) {
1359
- options = placemark.getMarkerOptions();
1391
+ if (edgePadding != null) {
1392
+ appendMapPadding(edgePadding.getInt("left"), edgePadding.getInt("top"), edgePadding.getInt("right"), edgePadding.getInt("bottom"));
1393
+ }
1394
+
1395
+ if (animated) {
1396
+ map.animateCamera(cu);
1360
1397
  } else {
1361
- options.icon(BitmapDescriptorFactory.defaultMarker());
1398
+ map.moveCamera(cu);
1362
1399
  }
1400
+ // Move the google logo to the default base padding value.
1401
+ map.setPadding(baseLeftMapPadding, baseTopMapPadding, baseRightMapPadding, baseBottomMapPadding);
1402
+ }
1363
1403
 
1364
- LatLng latLng = ((LatLng) placemark.getGeometry().getGeometryObject());
1365
- String title = "";
1366
- String snippet = "";
1404
+ private void appendMapPadding(int iLeft, int iTop, int iRight, int iBottom) {
1405
+ double density = getResources().getDisplayMetrics().density;
1406
+
1407
+ edgeLeftPadding = (int) (iLeft * density);
1408
+ edgeTopPadding = (int) (iTop * density);
1409
+ edgeRightPadding = (int) (iRight * density);
1410
+ edgeBottomPadding = (int) (iBottom * density);
1411
+
1412
+ map.setPadding(edgeLeftPadding + baseLeftMapPadding,
1413
+ edgeTopPadding + baseTopMapPadding,
1414
+ edgeRightPadding + baseRightMapPadding,
1415
+ edgeBottomPadding + baseBottomMapPadding);
1416
+ }
1417
+
1418
+ public double[][] getMapBoundaries() {
1419
+ LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
1420
+ LatLng northEast = bounds.northeast;
1421
+ LatLng southWest = bounds.southwest;
1422
+
1423
+ return new double[][]{
1424
+ {northEast.longitude, northEast.latitude},
1425
+ {southWest.longitude, southWest.latitude}
1426
+ };
1427
+ }
1367
1428
 
1368
- if (placemark.hasProperty("name")) {
1369
- title = placemark.getProperty("name");
1429
+ public void setMapBoundaries(ReadableMap northEast, ReadableMap southWest) {
1430
+ if (map == null) return;
1431
+
1432
+ LatLngBounds.Builder builder = new LatLngBounds.Builder();
1433
+
1434
+ double latNE = northEast.getDouble("latitude");
1435
+ double lngNE = northEast.getDouble("longitude");
1436
+ builder.include(new LatLng(latNE, lngNE));
1437
+
1438
+ double latSW = southWest.getDouble("latitude");
1439
+ double lngSW = southWest.getDouble("longitude");
1440
+ builder.include(new LatLng(latSW, lngSW));
1441
+
1442
+ LatLngBounds bounds = builder.build();
1443
+
1444
+ map.setLatLngBoundsForCameraTarget(bounds);
1445
+ }
1446
+
1447
+ // InfoWindowAdapter interface
1448
+
1449
+ @Override
1450
+ public View getInfoWindow(Marker marker) {
1451
+ MapMarker markerView = getMarkerMap(marker);
1452
+ return markerView.getCallout();
1453
+ }
1454
+
1455
+ @Override
1456
+ public View getInfoContents(Marker marker) {
1457
+ MapMarker markerView = getMarkerMap(marker);
1458
+ return markerView.getInfoContents();
1459
+ }
1460
+
1461
+ @Override
1462
+ public boolean dispatchTouchEvent(MotionEvent ev) {
1463
+ gestureDetector.onTouchEvent(ev);
1464
+
1465
+ int X = (int) ev.getX();
1466
+ int Y = (int) ev.getY();
1467
+ if (map != null) {
1468
+ tapLocation = map.getProjection().fromScreenLocation(new Point(X, Y));
1370
1469
  }
1371
1470
 
1372
- if (placemark.hasProperty("description")) {
1373
- snippet = placemark.getProperty("description");
1471
+ int action = MotionEventCompat.getActionMasked(ev);
1472
+
1473
+ switch (action) {
1474
+ case (MotionEvent.ACTION_DOWN):
1475
+ this.getParent().requestDisallowInterceptTouchEvent(
1476
+ map != null && map.getUiSettings().isScrollGesturesEnabled());
1477
+ break;
1478
+ case (MotionEvent.ACTION_UP):
1479
+ // Clear this regardless, since isScrollGesturesEnabled() may have been updated
1480
+ this.getParent().requestDisallowInterceptTouchEvent(false);
1481
+ break;
1374
1482
  }
1483
+ super.dispatchTouchEvent(ev);
1484
+ return true;
1485
+ }
1375
1486
 
1376
- options.position(latLng);
1377
- options.title(title);
1378
- options.snippet(snippet);
1487
+ @Override
1488
+ public void onMarkerDragStart(Marker marker) {
1489
+ WritableMap event = makeClickEventData(marker.getPosition());
1490
+ dispatchEvent(event, OnMarkerDragStartEvent::new);
1379
1491
 
1492
+ MapMarker markerView = getMarkerMap(marker);
1493
+ event = makeClickEventData(marker.getPosition());
1494
+ dispatchEvent(event, OnMarkerDragStartEvent::new, markerView.getId(), context);
1495
+ }
1496
+
1497
+ @Override
1498
+ public void onMarkerDrag(Marker marker) {
1499
+ WritableMap event = makeClickEventData(marker.getPosition());
1500
+ dispatchEvent(event, OnMarkerDragEvent::new);
1501
+
1502
+ MapMarker markerView = getMarkerMap(marker);
1503
+ event = makeClickEventData(marker.getPosition());
1504
+ dispatchEvent(event, OnMarkerDragEvent::new, markerView.getId(), context);
1505
+ }
1506
+
1507
+ @Override
1508
+ public void onMarkerDragEnd(Marker marker) {
1509
+ WritableMap event = makeClickEventData(marker.getPosition());
1510
+ dispatchEvent(event, OnMarkerDragEndEvent::new);
1511
+ MapMarker markerView = getMarkerMap(marker);
1512
+ event = makeClickEventData(marker.getPosition());
1513
+ dispatchEvent(event, OnMarkerDragEndEvent::new, markerView.getId(), context);
1514
+ }
1515
+
1516
+ @Override
1517
+ public void onPoiClick(PointOfInterest poi) {
1518
+ WritableMap event = makeClickEventData(poi.latLng);
1519
+
1520
+ event.putString("placeId", poi.placeId);
1521
+ event.putString("name", poi.name);
1522
+ dispatchEvent(event, OnPoiClickEvent::new);
1523
+ }
1524
+
1525
+ private ProgressBar getMapLoadingProgressBar() {
1526
+ if (this.mapLoadingProgressBar == null) {
1527
+ this.mapLoadingProgressBar = new ProgressBar(getContext());
1528
+ this.mapLoadingProgressBar.setIndeterminate(true);
1529
+ }
1530
+ if (this.loadingIndicatorColor != null) {
1531
+ this.setLoadingIndicatorColor(this.loadingIndicatorColor);
1532
+ }
1533
+ return this.mapLoadingProgressBar;
1534
+ }
1535
+
1536
+ private RelativeLayout getMapLoadingLayoutView() {
1537
+ if (this.mapLoadingLayout == null) {
1538
+ this.mapLoadingLayout = new RelativeLayout(getContext());
1539
+ this.mapLoadingLayout.setBackgroundColor(Color.LTGRAY);
1540
+ this.addView(this.mapLoadingLayout,
1541
+ new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
1542
+ ViewGroup.LayoutParams.MATCH_PARENT));
1543
+
1544
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
1545
+ RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
1546
+ params.addRule(RelativeLayout.CENTER_IN_PARENT);
1547
+ this.mapLoadingLayout.addView(this.getMapLoadingProgressBar(), params);
1548
+
1549
+ this.mapLoadingLayout.setVisibility(View.INVISIBLE);
1550
+ }
1551
+ this.setLoadingBackgroundColor(this.loadingBackgroundColor);
1552
+ return this.mapLoadingLayout;
1553
+ }
1554
+
1555
+ private ImageView getCacheImageView() {
1556
+ if (this.cacheImageView == null) {
1557
+ this.cacheImageView = new ImageView(getContext());
1558
+ this.addView(this.cacheImageView,
1559
+ new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
1560
+ ViewGroup.LayoutParams.MATCH_PARENT));
1561
+ this.cacheImageView.setVisibility(View.INVISIBLE);
1562
+ }
1563
+ return this.cacheImageView;
1564
+ }
1565
+
1566
+ private void removeCacheImageView() {
1567
+ if (this.cacheImageView != null) {
1568
+ ((ViewGroup) this.cacheImageView.getParent()).removeView(this.cacheImageView);
1569
+ this.cacheImageView = null;
1570
+ }
1571
+ }
1572
+
1573
+ private void removeMapLoadingProgressBar() {
1574
+ if (this.mapLoadingProgressBar != null) {
1575
+ ((ViewGroup) this.mapLoadingProgressBar.getParent()).removeView(this.mapLoadingProgressBar);
1576
+ this.mapLoadingProgressBar = null;
1577
+ }
1578
+ }
1579
+
1580
+ private void removeMapLoadingLayoutView() {
1581
+ this.removeMapLoadingProgressBar();
1582
+ if (this.mapLoadingLayout != null) {
1583
+ ((ViewGroup) this.mapLoadingLayout.getParent()).removeView(this.mapLoadingLayout);
1584
+ this.mapLoadingLayout = null;
1585
+ }
1586
+ }
1587
+
1588
+ private void cacheView() {
1589
+ if (this.cacheEnabled) {
1590
+ final ImageView cacheImageView = this.getCacheImageView();
1591
+ final RelativeLayout mapLoadingLayout = this.getMapLoadingLayoutView();
1592
+ cacheImageView.setVisibility(View.INVISIBLE);
1593
+ mapLoadingLayout.setVisibility(View.VISIBLE);
1594
+ if (this.isMapLoaded) {
1595
+ this.map.snapshot(new GoogleMap.SnapshotReadyCallback() {
1596
+ @Override
1597
+ public void onSnapshotReady(Bitmap bitmap) {
1598
+ cacheImageView.setImageBitmap(bitmap);
1599
+ cacheImageView.setVisibility(View.VISIBLE);
1600
+ mapLoadingLayout.setVisibility(View.INVISIBLE);
1601
+ }
1602
+ });
1603
+ }
1604
+ } else {
1605
+ this.removeCacheImageView();
1606
+ if (this.isMapLoaded) {
1607
+ this.removeMapLoadingLayoutView();
1608
+ }
1609
+ }
1610
+ }
1611
+
1612
+ public void onPanDrag(MotionEvent ev) {
1613
+ Point point = new Point((int) ev.getX(), (int) ev.getY());
1614
+ LatLng coords = this.map.getProjection().fromScreenLocation(point);
1615
+ WritableMap event = makeClickEventData(coords);
1616
+ dispatchEvent(event, OnPanDragEvent::new);
1617
+ }
1618
+
1619
+ public void onDoublePress(MotionEvent ev) {
1620
+ if (this.map == null) return;
1621
+ Point point = new Point((int) ev.getX(), (int) ev.getY());
1622
+ LatLng coords = this.map.getProjection().fromScreenLocation(point);
1623
+ WritableMap event = makeClickEventData(coords);
1624
+ dispatchEvent(event, OnDoublePressEvent::new);
1625
+
1626
+ }
1627
+
1628
+ public void setKmlSrc(String kmlSrc) {
1629
+ if (isMapReady) {
1630
+ try {
1631
+ InputStream kmlStream = new FileUtil(context).execute(kmlSrc).get();
1632
+
1633
+ if (kmlStream == null) {
1634
+ return;
1635
+ }
1636
+
1637
+ KmlLayer kmlLayer = new KmlLayer(map, kmlStream, context, markerManager, polygonManager, polylineManager, groundOverlayManager, null);
1638
+
1639
+ kmlLayer.addLayerToMap();
1640
+
1641
+ WritableMap pointers = new WritableNativeMap();
1642
+ WritableArray markers = new WritableNativeArray();
1643
+
1644
+ if (kmlLayer.getContainers() == null) {
1645
+ // todo: use Fabric events
1646
+ // manager.pushEvent(context, this, "onKmlReady", pointers);
1647
+ return;
1648
+ }
1649
+
1650
+ //Retrieve a nested container within the first container
1651
+ KmlContainer container = kmlLayer.getContainers().iterator().next();
1652
+ if (container == null || container.getContainers() == null) {
1653
+ // todo: use Fabric events
1654
+ // manager.pushEvent(context, this, "onKmlReady", pointers);
1655
+ return;
1656
+ }
1657
+
1658
+
1659
+ if (container.getContainers().iterator().hasNext()) {
1660
+ container = container.getContainers().iterator().next();
1661
+ }
1662
+
1663
+ int index = 0;
1664
+ for (KmlPlacemark placemark : container.getPlacemarks()) {
1665
+ MarkerOptions options = new MarkerOptions();
1666
+
1667
+ if (placemark.getInlineStyle() != null) {
1668
+ options = placemark.getMarkerOptions();
1669
+ } else {
1670
+ options.icon(BitmapDescriptorFactory.defaultMarker());
1671
+ }
1672
+
1673
+ LatLng latLng = ((LatLng) placemark.getGeometry().getGeometryObject());
1674
+ String title = "";
1675
+ String snippet = "";
1676
+
1677
+ if (placemark.hasProperty("name")) {
1678
+ title = placemark.getProperty("name");
1679
+ }
1680
+
1681
+ if (placemark.hasProperty("description")) {
1682
+ snippet = placemark.getProperty("description");
1683
+ }
1684
+
1685
+ options.position(latLng);
1686
+ options.title(title);
1687
+ options.snippet(snippet);
1688
+ // FIXME: get markerManager from somewhere
1689
+ /*
1380
1690
  MapMarker marker = new MapMarker(context, options, this.manager.getMarkerManager());
1381
1691
 
1382
1692
  if (placemark.getInlineStyle() != null
@@ -1393,127 +1703,130 @@ public static CameraPosition cameraPositionFromMap(ReadableMap camera){
1393
1703
 
1394
1704
  addFeature(marker, index++);
1395
1705
 
1706
+
1396
1707
  WritableMap loadedMarker = makeClickEventData(latLng);
1397
1708
  loadedMarker.putString("id", identifier);
1398
1709
  loadedMarker.putString("title", title);
1399
1710
  loadedMarker.putString("description", snippet);
1400
1711
 
1401
1712
  markers.pushMap(loadedMarker);
1402
- }
1403
-
1404
- pointers.putArray("markers", markers);
1405
-
1406
- manager.pushEvent(context, this, "onKmlReady", pointers);
1407
-
1408
- } catch (XmlPullParserException | IOException | InterruptedException | ExecutionException e) {
1409
- e.printStackTrace();
1410
- }
1411
- }
1412
-
1413
- @Override
1414
- public void onIndoorBuildingFocused() {
1415
- IndoorBuilding building = this.map.getFocusedBuilding();
1416
- if (building != null) {
1417
- List<IndoorLevel> levels = building.getLevels();
1418
- int index = 0;
1419
- WritableArray levelsArray = Arguments.createArray();
1420
- for (IndoorLevel level : levels) {
1421
- WritableMap levelMap = Arguments.createMap();
1422
- levelMap.putInt("index", index);
1423
- levelMap.putString("name", level.getName());
1424
- levelMap.putString("shortName", level.getShortName());
1425
- levelsArray.pushMap(levelMap);
1426
- index++;
1427
- }
1428
- WritableMap event = Arguments.createMap();
1429
- WritableMap indoorBuilding = Arguments.createMap();
1430
- indoorBuilding.putArray("levels", levelsArray);
1431
- indoorBuilding.putInt("activeLevelIndex", building.getActiveLevelIndex());
1432
- indoorBuilding.putBoolean("underground", building.isUnderground());
1433
-
1434
- event.putMap("IndoorBuilding", indoorBuilding);
1435
-
1436
- manager.pushEvent(context, this, "onIndoorBuildingFocused", event);
1437
- } else {
1438
- WritableMap event = Arguments.createMap();
1439
- WritableArray levelsArray = Arguments.createArray();
1440
- WritableMap indoorBuilding = Arguments.createMap();
1441
- indoorBuilding.putArray("levels", levelsArray);
1442
- indoorBuilding.putInt("activeLevelIndex", 0);
1443
- indoorBuilding.putBoolean("underground", false);
1444
-
1445
- event.putMap("IndoorBuilding", indoorBuilding);
1446
-
1447
- manager.pushEvent(context, this, "onIndoorBuildingFocused", event);
1448
- }
1449
- }
1450
-
1451
- @Override
1452
- public void onIndoorLevelActivated(IndoorBuilding building) {
1453
- if (building == null) {
1454
- return;
1455
- }
1456
- int activeLevelIndex = building.getActiveLevelIndex();
1457
- if (activeLevelIndex < 0 || activeLevelIndex >= building.getLevels().size()) {
1458
- return;
1459
- }
1460
- IndoorLevel level = building.getLevels().get(activeLevelIndex);
1461
-
1462
- WritableMap event = Arguments.createMap();
1463
- WritableMap indoorlevel = Arguments.createMap();
1464
-
1465
- indoorlevel.putInt("activeLevelIndex", activeLevelIndex);
1466
- indoorlevel.putString("name", level.getName());
1467
- indoorlevel.putString("shortName", level.getShortName());
1468
-
1469
- event.putMap("IndoorLevel", indoorlevel);
1470
-
1471
- manager.pushEvent(context, this, "onIndoorLevelActivated", event);
1472
- }
1473
-
1474
- public void setIndoorActiveLevelIndex(int activeLevelIndex) {
1475
- IndoorBuilding building = this.map.getFocusedBuilding();
1476
- if (building != null) {
1477
- if (activeLevelIndex >= 0 && activeLevelIndex < building.getLevels().size()) {
1478
- IndoorLevel level = building.getLevels().get(activeLevelIndex);
1479
- if (level != null) {
1480
- level.activate();
1713
+ */
1714
+ }
1715
+
1716
+ pointers.putArray("markers", markers);
1717
+ // todo: use Fabric events
1718
+ // manager.pushEvent(context, this, "onKmlReady", pointers);
1719
+
1720
+ } catch (XmlPullParserException | IOException | InterruptedException |
1721
+ ExecutionException e) {
1722
+ e.printStackTrace();
1723
+ }
1724
+ } else {
1725
+ this.kmlSrc = kmlSrc;
1481
1726
  }
1482
- }
1483
1727
  }
1484
- }
1485
1728
 
1486
- private MapMarker getMarkerMap(Marker marker) {
1487
- MapMarker airMarker = markerMap.get(marker);
1729
+ @Override
1730
+ public void onIndoorBuildingFocused() {
1731
+ IndoorBuilding building = this.map.getFocusedBuilding();
1732
+ if (building != null) {
1733
+ List<IndoorLevel> levels = building.getLevels();
1734
+ int index = 0;
1735
+ WritableArray levelsArray = Arguments.createArray();
1736
+ for (IndoorLevel level : levels) {
1737
+ WritableMap levelMap = Arguments.createMap();
1738
+ levelMap.putInt("index", index);
1739
+ levelMap.putString("name", level.getName());
1740
+ levelMap.putString("shortName", level.getShortName());
1741
+ levelsArray.pushMap(levelMap);
1742
+ index++;
1743
+ }
1744
+ WritableMap event = Arguments.createMap();
1745
+ WritableMap indoorBuilding = Arguments.createMap();
1746
+ indoorBuilding.putArray("levels", levelsArray);
1747
+ indoorBuilding.putInt("activeLevelIndex", building.getActiveLevelIndex());
1748
+ indoorBuilding.putBoolean("underground", building.isUnderground());
1749
+
1750
+ event.putMap("indoorBuilding", indoorBuilding);
1751
+ dispatchEvent(event, OnIndoorBuildingFocusedEvent::new);
1752
+ } else {
1753
+ WritableMap event = Arguments.createMap();
1754
+ WritableArray levelsArray = Arguments.createArray();
1755
+ WritableMap indoorBuilding = Arguments.createMap();
1756
+ indoorBuilding.putArray("levels", levelsArray);
1757
+ indoorBuilding.putInt("activeLevelIndex", 0);
1758
+ indoorBuilding.putBoolean("underground", false);
1759
+
1760
+ event.putMap("indoorBuilding", indoorBuilding);
1761
+ dispatchEvent(event, OnIndoorBuildingFocusedEvent::new);
1762
+ }
1763
+ }
1488
1764
 
1489
- if (airMarker != null) {
1490
- return airMarker;
1765
+ @Override
1766
+ public void onIndoorLevelActivated(IndoorBuilding building) {
1767
+ if (building == null) {
1768
+ return;
1769
+ }
1770
+ int activeLevelIndex = building.getActiveLevelIndex();
1771
+ if (activeLevelIndex < 0 || activeLevelIndex >= building.getLevels().size()) {
1772
+ return;
1773
+ }
1774
+ IndoorLevel level = building.getLevels().get(activeLevelIndex);
1775
+
1776
+ WritableMap event = Arguments.createMap();
1777
+ WritableMap indoorlevel = Arguments.createMap();
1778
+
1779
+ indoorlevel.putInt("activeLevelIndex", activeLevelIndex);
1780
+ indoorlevel.putString("name", level.getName());
1781
+ indoorlevel.putString("shortName", level.getShortName());
1782
+
1783
+ event.putMap("indoorLevel", indoorlevel);
1784
+ dispatchEvent(event, OnIndoorLevelActivatedEvent::new);
1491
1785
  }
1492
1786
 
1493
- for (Map.Entry<Marker, MapMarker> entryMarker : markerMap.entrySet()) {
1494
- if (entryMarker.getKey().getPosition().equals(marker.getPosition())
1495
- && entryMarker.getKey().getTitle().equals(marker.getTitle())) {
1496
- airMarker = entryMarker.getValue();
1497
- break;
1498
- }
1787
+ public void setIndoorActiveLevelIndex(int activeLevelIndex) {
1788
+ IndoorBuilding building = this.map.getFocusedBuilding();
1789
+ if (building != null) {
1790
+ if (activeLevelIndex >= 0 && activeLevelIndex < building.getLevels().size()) {
1791
+ IndoorLevel level = building.getLevels().get(activeLevelIndex);
1792
+ if (level != null) {
1793
+ level.activate();
1794
+ }
1795
+ }
1796
+ }
1499
1797
  }
1500
1798
 
1501
- return airMarker;
1502
- }
1799
+ private MapMarker getMarkerMap(Marker marker) {
1800
+ MapMarker airMarker = markerMap.get(marker);
1801
+
1802
+ if (airMarker != null) {
1803
+ return airMarker;
1804
+ }
1805
+
1806
+ for (Map.Entry<Marker, MapMarker> entryMarker : markerMap.entrySet()) {
1807
+ if (entryMarker.getKey().getPosition().equals(marker.getPosition())
1808
+ && entryMarker.getKey().getTitle().equals(marker.getTitle())) {
1809
+ airMarker = entryMarker.getValue();
1810
+ break;
1811
+ }
1812
+ }
1503
1813
 
1504
- @Override
1505
- public void requestLayout() {
1506
- super.requestLayout();
1507
- post(measureAndLayout);
1508
- }
1814
+ return airMarker;
1815
+ }
1509
1816
 
1510
- private final Runnable measureAndLayout = new Runnable() {
1511
1817
  @Override
1512
- public void run() {
1513
- measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY),
1514
- MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY));
1515
- layout(getLeft(), getTop(), getRight(), getBottom());
1818
+ public void requestLayout() {
1819
+ super.requestLayout();
1820
+ post(measureAndLayout);
1516
1821
  }
1517
- };
1822
+
1823
+ private final Runnable measureAndLayout = new Runnable() {
1824
+ @Override
1825
+ public void run() {
1826
+ measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY),
1827
+ MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY));
1828
+ layout(getLeft(), getTop(), getRight(), getBottom());
1829
+ }
1830
+ };
1518
1831
 
1519
1832
  }