Added ability to use a custom view for MapView annotations

Summary:
public
This diff adds the ability to specify a custom React component (aka view) to be displayed as a MapView pin.

This makes it possible to use remote images (using an <Image/> component), or text (using a <Text/> component), or anything else.

One consequence of this is that MapView can no longer support arbitrary subviews. To place views in front the map, add them to a separate container view.

Reviewed By: tadeuzagallo

Differential Revision: D2764790

fb-gh-sync-id: e16b44e866c2d76c76b0cb35ef9eefbfc68d6719
This commit is contained in:
Nick Lockwood
2015-12-17 06:45:53 -08:00
committed by facebook-github-bot-6
parent 97c75cf5a4
commit f9dfb90a35
8 changed files with 339 additions and 297 deletions

View File

@@ -17,10 +17,12 @@
var React = require('react-native');
var {
Image,
MapView,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View,
} = React;
@@ -239,14 +241,14 @@ var MapViewExample = React.createClass({
});
type CalloutMapViewExampleState = {
type AnnotationExampleState = {
isFirstLoad: boolean,
annotations?: Annotations,
mapRegion?: MapRegion,
};
var CalloutMapViewExample = React.createClass({
var AnnotationExample = React.createClass({
getInitialState(): CalloutMapViewExampleState {
getInitialState(): AnnotationExampleState {
return {
isFirstLoad: true,
};
@@ -260,11 +262,7 @@ var CalloutMapViewExample = React.createClass({
annotations: [{
longitude: region.longitude,
latitude: region.latitude,
title: 'More Info...',
hasRightCallout: true,
onRightCalloutPress: () => {
alert('You Are Here');
},
...this.props.annotation,
}],
});
};
@@ -282,141 +280,6 @@ var CalloutMapViewExample = React.createClass({
});
type CustomPinColorMapViewExampleState = {
isFirstLoad: boolean,
annotations?: Annotations,
mapRegion?: MapRegion,
};
var CustomPinColorMapViewExample = React.createClass({
getInitialState(): CustomPinColorMapViewExampleState {
return {
isFirstLoad: true,
};
},
render() {
if (this.state.isFirstLoad) {
var onRegionChangeComplete = (region) => {
this.setState({
isFirstLoad: false,
annotations: [{
longitude: region.longitude,
latitude: region.latitude,
title: 'You Are Purple',
tintColor: MapView.PinColors.PURPLE,
}],
});
};
}
return (
<MapView
style={styles.map}
onRegionChangeComplete={onRegionChangeComplete}
region={this.state.mapRegion}
annotations={this.state.annotations}
/>
);
},
});
type CustomPinImageMapViewExampleState = {
isFirstLoad: boolean,
annotations?: Annotations,
mapRegion?: MapRegion,
};
var CustomPinImageMapViewExample = React.createClass({
getInitialState(): CustomPinImageMapViewExampleState {
return {
isFirstLoad: true,
};
},
render() {
if (this.state.isFirstLoad) {
var onRegionChangeComplete = (region) => {
this.setState({
isFirstLoad: false,
annotations: [{
longitude: region.longitude,
latitude: region.latitude,
title: 'Thumbs Up!',
image: require('image!uie_thumb_big'),
}],
});
};
}
return (
<MapView
style={styles.map}
onRegionChangeComplete={onRegionChangeComplete}
region={this.state.mapRegion}
annotations={this.state.annotations}
/>
);
},
});
type Overlays = Array<{
coordinates?: Array<{
latitude: number,
longitude: number,
}>,
lineWidth?: number,
strokeColor?: string,
fillColor?: string,
id?: string,
}>;
type CustomOverlayMapViewExampleState = {
isFirstLoad: boolean,
overlays?: Overlays,
annotations?: Annotations,
mapRegion?: MapRegion,
};
var CustomOverlayMapViewExample = React.createClass({
getInitialState(): CustomOverlayMapViewExampleState {
return {
isFirstLoad: true,
};
},
render() {
if (this.state.isFirstLoad) {
var onRegionChangeComplete = (region) => {
this.setState({
isFirstLoad: false,
overlays: [{
coordinates:[
{latitude: 32.47, longitude: -107.85},
{latitude: 45.13, longitude: -94.48},
{latitude: 39.27, longitude: -83.25},
{latitude: 32.47, longitude: -107.85},
],
strokeColor: '#f007',
lineWidth: 3,
}],
});
};
}
return (
<MapView
style={styles.map}
onRegionChangeComplete={onRegionChangeComplete}
region={this.state.mapRegion}
overlays={this.state.overlays}
/>
);
},
});
var styles = StyleSheet.create({
map: {
height: 150,
@@ -451,36 +314,92 @@ exports.description = 'Base component to display maps';
exports.examples = [
{
title: 'Map',
render(): ReactElement { return <MapViewExample />; }
render() {
return <MapViewExample />;
}
},
{
title: 'Map shows user location',
render() {
return <MapView style={styles.map} showsUserLocation={true} />;
return <MapView style={styles.map} showsUserLocation={true} />;
}
},
{
title: 'Callout example',
render() {
return <CalloutMapViewExample style={styles.map} />;
return <AnnotationExample style={styles.map} annotation={{
title: 'More Info...',
rightCalloutView: (
<TouchableOpacity
onPress={() => {
alert('You Are Here');
}}>
<Image
style={{width:30, height:30}}
source={require('image!uie_thumb_selected')}
/>
</TouchableOpacity>
),
}}/>;
}
},
{
title: 'Custom pin color',
render() {
return <CustomPinColorMapViewExample style={styles.map} />;
return <AnnotationExample style={styles.map} annotation={{
title: 'You Are Purple',
tintColor: MapView.PinColors.PURPLE,
}}/>;
}
},
{
title: 'Custom pin image',
render() {
return <CustomPinImageMapViewExample style={styles.map} />;
return <AnnotationExample style={styles.map} annotation={{
title: 'Thumbs Up!',
image: require('image!uie_thumb_big'),
}}/>;
}
},
{
title: 'Custom pin view',
render() {
return <AnnotationExample style={styles.map} annotation={{
title: 'Thumbs Up!',
view: <View style={{
alignItems: 'center',
}}>
<Text style={{fontWeight: 'bold', color: '#f007'}}>
Thumbs Up!
</Text>
<Image
style={{width: 90, height: 65, resizeMode: 'cover'}}
source={require('image!uie_thumb_big')}
/>
</View>,
}}/>;
}
},
{
title: 'Custom overlay',
render() {
return <CustomOverlayMapViewExample style={styles.map} />;
return <MapView
style={styles.map}
region={{
latitude: 39.06,
longitude: -95.22,
}}
overlays={[{
coordinates:[
{latitude: 32.47, longitude: -107.85},
{latitude: 45.13, longitude: -94.48},
{latitude: 39.27, longitude: -83.25},
{latitude: 32.47, longitude: -107.85},
],
strokeColor: '#f007',
lineWidth: 3,
}]}
/>;
}
},
];