diff --git a/README.md b/README.md index 3d81e214c..05ed75170 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,24 @@ For Android: add the following line in your AndroidManifest.xml ``` For IOS: configure [App Transport Security](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33) in your app +### Customizing the map style +Create the json object, or download a generated one from the [google style generator](https://mapstyle.withgoogle.com/). + +```jsx +// The generated json object +mapStyle = [ ... ] + +render() { + return ( + + ); +} +``` ## Examples @@ -201,6 +218,11 @@ API could. ![](http://i.giphy.com/3o6UB7poyB6YJ0KPWU.gif) ![](http://i.giphy.com/xT77Yc4wK3pzZusEbm.gif) +### Changing the style of the map + +![](http://i.imgur.com/a9WqCL6.png) + + ### Arbitrary React Views as Markers diff --git a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java index 4273a31ed..75ed5777f 100644 --- a/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java +++ b/android/src/main/java/com/airbnb/android/react/maps/AirMapManager.java @@ -20,6 +20,7 @@ import com.google.android.gms.maps.MapsInitializer; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; +import com.google.android.gms.maps.model.MapStyleOptions; import java.util.Map; @@ -92,6 +93,11 @@ public void setMapType(AirMapView view, @Nullable String mapType) { int typeId = MAP_TYPES.get(mapType); view.map.setMapType(typeId); } + + @ReactProp(name = "customMapStyleString") + public void setMapStyle(AirMapView view, @Nullable String customMapStyleString) { + view.map.setMapStyle(new MapStyleOptions(customMapStyleString)); + } @ReactProp(name = "showsUserLocation", defaultBoolean = false) public void setShowsUserLocation(AirMapView view, boolean showUserLocation) { diff --git a/components/MapView.js b/components/MapView.js index b50ab8aac..4eac41c94 100644 --- a/components/MapView.js +++ b/components/MapView.js @@ -61,6 +61,21 @@ const propTypes = { */ style: View.propTypes.style, + /** + * A json object that describes the style of the map. This is transformed to a string + * and saved in mayStyleString to be sent to android and ios + * https://developers.google.com/maps/documentation/ios-sdk/styling#use_a_string_resource + * https://developers.google.com/maps/documentation/android-api/styling + */ + customMapStyle: PropTypes.array, + + /** + * A json string that describes the style of the map + * https://developers.google.com/maps/documentation/ios-sdk/styling#use_a_string_resource + * https://developers.google.com/maps/documentation/android-api/styling + */ + customMapStyleString: PropTypes.string, + /** * If `true` the app will ask for the user's location. * Default value is `false`. @@ -386,12 +401,15 @@ class MapView extends React.Component { } _onMapReady() { - const { region, initialRegion } = this.props; + const { region, initialRegion, customMapStyle } = this.props; if (region) { this.map.setNativeProps({ region }); } else if (initialRegion) { this.map.setNativeProps({ region: initialRegion }); } + if (customMapStyle) { + this.map.setNativeProps({ customMapStyleString: JSON.stringify(customMapStyle) }); + } this.setState({ isReady: true }); } diff --git a/example/App.js b/example/App.js index 39e3866a5..abd02acd2 100644 --- a/example/App.js +++ b/example/App.js @@ -31,6 +31,7 @@ import LiteMapView from './examples/LiteMapView'; import CustomTiles from './examples/CustomTiles'; import ZIndexMarkers from './examples/ZIndexMarkers'; import StaticMap from './examples/StaticMap'; +import MapStyle from './examples/MapStyle'; const IOS = Platform.OS === 'ios'; const ANDROID = Platform.OS === 'android'; @@ -140,6 +141,7 @@ class App extends React.Component { [LiteMapView, 'Android Lite MapView'], [CustomTiles, 'Custom Tiles', true], [ZIndexMarkers, 'Position Markers with Z-index', true], + [MapStyle, 'Customize the style of the map', true], ] // Filter out examples that are not yet supported for Google Maps on iOS. .filter(example => ANDROID || (IOS && (example[2] || !this.state.useGoogleMaps))) diff --git a/example/examples/MapStyle.js b/example/examples/MapStyle.js new file mode 100644 index 000000000..5d3416c93 --- /dev/null +++ b/example/examples/MapStyle.js @@ -0,0 +1,222 @@ +import React from 'react'; +import { + StyleSheet, + View, + Dimensions, +} from 'react-native'; + +import MapView from 'react-native-maps'; + +const { width, height } = Dimensions.get('window'); + +const ASPECT_RATIO = width / height; +const LATITUDE = 37.78825; +const LONGITUDE = -122.4324; +const LATITUDE_DELTA = 0.0922; +const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO; + +const customStyle = [ + { + elementType: 'geometry', + stylers: [ + { + color: '#242f3e', + }, + ], + }, + { + elementType: 'labels.text.fill', + stylers: [ + { + color: '#746855', + }, + ], + }, + { + elementType: 'labels.text.stroke', + stylers: [ + { + color: '#242f3e', + }, + ], + }, + { + featureType: 'administrative.locality', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#d59563', + }, + ], + }, + { + featureType: 'poi', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#d59563', + }, + ], + }, + { + featureType: 'poi.park', + elementType: 'geometry', + stylers: [ + { + color: '#263c3f', + }, + ], + }, + { + featureType: 'poi.park', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#6b9a76', + }, + ], + }, + { + featureType: 'road', + elementType: 'geometry', + stylers: [ + { + color: '#38414e', + }, + ], + }, + { + featureType: 'road', + elementType: 'geometry.stroke', + stylers: [ + { + color: '#212a37', + }, + ], + }, + { + featureType: 'road', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#9ca5b3', + }, + ], + }, + { + featureType: 'road.highway', + elementType: 'geometry', + stylers: [ + { + color: '#746855', + }, + ], + }, + { + featureType: 'road.highway', + elementType: 'geometry.stroke', + stylers: [ + { + color: '#1f2835', + }, + ], + }, + { + featureType: 'road.highway', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#f3d19c', + }, + ], + }, + { + featureType: 'transit', + elementType: 'geometry', + stylers: [ + { + color: '#2f3948', + }, + ], + }, + { + featureType: 'transit.station', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#d59563', + }, + ], + }, + { + featureType: 'water', + elementType: 'geometry', + stylers: [ + { + color: '#17263c', + }, + ], + }, + { + featureType: 'water', + elementType: 'labels.text.fill', + stylers: [ + { + color: '#515c6d', + }, + ], + }, + { + featureType: 'water', + elementType: 'labels.text.stroke', + stylers: [ + { + color: '#17263c', + }, + ], + }, +]; + +class MapStyle extends React.Component { + constructor(props) { + super(props); + + this.state = { + }; + } + + render() { + return ( + + + + ); + } +} + +MapStyle.propTypes = { + provider: MapView.ProviderPropType, +}; + +const styles = StyleSheet.create({ + container: { + ...StyleSheet.absoluteFillObject, + justifyContent: 'flex-end', + alignItems: 'center', + }, + map: { + ...StyleSheet.absoluteFillObject, + }, +}); + +module.exports = MapStyle;