mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-03-27 22:54:46 +08:00
[MapView] Support for annotation callouts, annotation press, callout presses and pin animation
Summary: Started from here - https://github.com/facebook/react-native/issues/1120. Most functionality for annotations were missing so I started implementing and somehow got caught up until the entire thing was done.  2 new events: - callout presses (left / right) - annotation presses 6 new properties for annotations: - hasLeftCallout - hasRightCallout - onLeftCalloutPress - onRightCalloutPress - animateDrop - id 1 new property for MapView - onAnnotationPress --- Now the important thing is, that I implemented all of this the way "I would do it". I am not sure this is the 'reacty' way so please let me know my mistakes 😄 The problem is that there is no real way to identify annotations which makes it difficult to distinguish which one got clicked. The idea is to pass a `id` and whether it has callouts the entire way with the annotation. I had to Closes https://github.com/facebook/react-native/pull/1247 Github Author: David Mohl <me@dave.cx> Test Plan: Imported from GitHub, without a `Test Plan:` line.
This commit is contained in:
@@ -35,6 +35,34 @@ type MapRegion = {
|
||||
var MapView = React.createClass({
|
||||
mixins: [NativeMethodsMixin],
|
||||
|
||||
checkAnnotationIds: function (annotations: Array<Object>) {
|
||||
|
||||
var newAnnotations = annotations.map(function (annotation) {
|
||||
if (!annotation.id) {
|
||||
// TODO: add a base64 (or similar) encoder here
|
||||
annotation.id = encodeURIComponent(JSON.stringify(annotation));
|
||||
}
|
||||
|
||||
return annotation;
|
||||
});
|
||||
|
||||
this.setState({
|
||||
annotations: newAnnotations
|
||||
});
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
if (this.props.annotations) {
|
||||
this.checkAnnotationIds(this.props.annotations);
|
||||
}
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps: Object) {
|
||||
if (nextProps.annotations) {
|
||||
this.checkAnnotationIds(nextProps.annotations);
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
/**
|
||||
* Used to style and layout the `MapView`. See `StyleSheet.js` and
|
||||
@@ -84,14 +112,14 @@ var MapView = React.createClass({
|
||||
|
||||
/**
|
||||
* The map type to be displayed.
|
||||
*
|
||||
*
|
||||
* - standard: standard road map (default)
|
||||
* - satellite: satellite view
|
||||
* - hybrid: satellite view with roads and points of interest overlayed
|
||||
*/
|
||||
mapType: React.PropTypes.oneOf([
|
||||
'standard',
|
||||
'satellite',
|
||||
'standard',
|
||||
'satellite',
|
||||
'hybrid',
|
||||
]),
|
||||
|
||||
@@ -126,11 +154,34 @@ var MapView = React.createClass({
|
||||
latitude: React.PropTypes.number.isRequired,
|
||||
longitude: React.PropTypes.number.isRequired,
|
||||
|
||||
/**
|
||||
* Whether the pin drop should be animated or not
|
||||
*/
|
||||
animateDrop: React.PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Annotation title/subtile.
|
||||
*/
|
||||
title: React.PropTypes.string,
|
||||
subtitle: React.PropTypes.string,
|
||||
|
||||
/**
|
||||
* Whether the Annotation has callout buttons.
|
||||
*/
|
||||
hasLeftCallout: React.PropTypes.bool,
|
||||
hasRightCallout: React.PropTypes.bool,
|
||||
|
||||
/**
|
||||
* Event handlers for callout buttons.
|
||||
*/
|
||||
onLeftCalloutPress: React.PropTypes.func,
|
||||
onRightCalloutPress: React.PropTypes.func,
|
||||
|
||||
/**
|
||||
* annotation id
|
||||
*/
|
||||
id: React.PropTypes.string
|
||||
|
||||
})),
|
||||
|
||||
/**
|
||||
@@ -158,6 +209,11 @@ var MapView = React.createClass({
|
||||
* Callback that is called once, when the user is done moving the map.
|
||||
*/
|
||||
onRegionChangeComplete: React.PropTypes.func,
|
||||
|
||||
/**
|
||||
* Callback that is called once, when the user is clicked on a annotation.
|
||||
*/
|
||||
onAnnotationPress: React.PropTypes.func,
|
||||
},
|
||||
|
||||
_onChange: function(event: Event) {
|
||||
@@ -170,8 +226,34 @@ var MapView = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
_onPress: function(event: Event) {
|
||||
if (event.nativeEvent.action === 'annotation-click') {
|
||||
this.props.onAnnotationPress && this.props.onAnnotationPress(event.nativeEvent.annotation);
|
||||
}
|
||||
|
||||
if (event.nativeEvent.action === 'callout-click') {
|
||||
if (!this.props.annotations) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the annotation with the id of what has been pressed
|
||||
for (var i = 0; i < this.props.annotations.length; i++) {
|
||||
var annotation = this.props.annotations[i];
|
||||
if (annotation.id === event.nativeEvent.annotationId) {
|
||||
// Pass the right function
|
||||
if (event.nativeEvent.side === 'left') {
|
||||
annotation.onLeftCalloutPress && annotation.onLeftCalloutPress(event.nativeEvent);
|
||||
} else if (event.nativeEvent.side === 'right') {
|
||||
annotation.onRightCalloutPress && annotation.onRightCalloutPress(event.nativeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return <RCTMap {...this.props} onChange={this._onChange} />;
|
||||
return <RCTMap {...this.props} onPress={this._onPress} onChange={this._onChange} />;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user