mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-29 21:46:07 +08:00
Add MapView annotation callback when it gets / lost the focus
Summary: For my project it was required to receive a notification when the MapView annotation was deselected. So I renamed `onAnnotationPress` to `onAnnotationSelected` and added a new method `onAnnotationDeselected`, this names was "inspired" by the underlaying iOS API. The old API was still called and marked as deprecated. But maybe you have an idea for a better naming (onAnnotationFocus/-Blur?) -- or should a deselected call the press method again without an annotation (undefined)? Closes https://github.com/facebook/react-native/pull/5167 Reviewed By: svcscm Differential Revision: D2869695 Pulled By: nicklockwood fb-gh-sync-id: 91795ac3f1e4533b250af8901534d8870729d9db
This commit is contained in:
committed by
facebook-github-bot-4
parent
53100ecccb
commit
cb874a55aa
@@ -320,6 +320,20 @@ exports.examples = [
|
|||||||
}}/>;
|
}}/>;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Annotation focus example',
|
||||||
|
render() {
|
||||||
|
return <AnnotationExample style={styles.map} annotation={{
|
||||||
|
title: 'More Info...',
|
||||||
|
onFocus: () => {
|
||||||
|
alert('Annotation gets focus');
|
||||||
|
},
|
||||||
|
onBlur: () => {
|
||||||
|
alert('Annotation lost focus');
|
||||||
|
}
|
||||||
|
}}/>;
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Draggable pin',
|
title: 'Draggable pin',
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -172,6 +172,18 @@ const MapView = React.createClass({
|
|||||||
*/
|
*/
|
||||||
onDragStateChange: React.PropTypes.func,
|
onDragStateChange: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event that fires when the annotation gets was tapped by the user
|
||||||
|
* and the callout view was displayed.
|
||||||
|
*/
|
||||||
|
onFocus: React.PropTypes.func,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event that fires when another annotation or the mapview itself
|
||||||
|
* was tapped and a previously shown annotation will be closed.
|
||||||
|
*/
|
||||||
|
onBlur: React.PropTypes.func,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation title/subtile.
|
* Annotation title/subtile.
|
||||||
*/
|
*/
|
||||||
@@ -288,7 +300,7 @@ const MapView = React.createClass({
|
|||||||
onRegionChangeComplete: React.PropTypes.func,
|
onRegionChangeComplete: React.PropTypes.func,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback that is called once, when the user taps an annotation.
|
* Deprecated. Use annotation onFocus and onBlur instead.
|
||||||
*/
|
*/
|
||||||
onAnnotationPress: React.PropTypes.func,
|
onAnnotationPress: React.PropTypes.func,
|
||||||
|
|
||||||
@@ -376,51 +388,61 @@ const MapView = React.createClass({
|
|||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: these should be separate events, to reduce bridge traffic
|
const findByAnnotationId = (annotationId: string) => {
|
||||||
if (annotations) {
|
if (!annotations) {
|
||||||
var onPress = (event: Event) => {
|
return null;
|
||||||
if (!annotations) {
|
}
|
||||||
return;
|
for (let i = 0, l = annotations.length; i < l; i++) {
|
||||||
|
if (annotations[i].id === annotationId) {
|
||||||
|
return annotations[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: these should be separate events, to reduce bridge traffic
|
||||||
|
let onPress, onAnnotationDragStateChange, onAnnotationFocus, onAnnotationBlur;
|
||||||
|
if (annotations) {
|
||||||
|
onPress = (event: Event) => {
|
||||||
if (event.nativeEvent.action === 'annotation-click') {
|
if (event.nativeEvent.action === 'annotation-click') {
|
||||||
|
// TODO: Remove deprecated onAnnotationPress API call later.
|
||||||
this.props.onAnnotationPress &&
|
this.props.onAnnotationPress &&
|
||||||
this.props.onAnnotationPress(event.nativeEvent.annotation);
|
this.props.onAnnotationPress(event.nativeEvent.annotation);
|
||||||
} else if (event.nativeEvent.action === 'callout-click') {
|
} else if (event.nativeEvent.action === 'callout-click') {
|
||||||
// Find the annotation with the id that was pressed
|
const annotation = findByAnnotationId(event.nativeEvent.annotationId);
|
||||||
for (let i = 0, l = annotations.length; i < l; i++) {
|
if (annotation) {
|
||||||
let annotation = annotations[i];
|
// Pass the right function
|
||||||
if (annotation.id === event.nativeEvent.annotationId) {
|
if (event.nativeEvent.side === 'left' && annotation.onLeftCalloutPress) {
|
||||||
// Pass the right function
|
annotation.onLeftCalloutPress(event.nativeEvent);
|
||||||
if (event.nativeEvent.side === 'left') {
|
} else if (event.nativeEvent.side === 'right' && annotation.onRightCalloutPress) {
|
||||||
annotation.onLeftCalloutPress &&
|
annotation.onRightCalloutPress(event.nativeEvent);
|
||||||
annotation.onLeftCalloutPress(event.nativeEvent);
|
|
||||||
} else if (event.nativeEvent.side === 'right') {
|
|
||||||
annotation.onRightCalloutPress &&
|
|
||||||
annotation.onRightCalloutPress(event.nativeEvent);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var onAnnotationDragStateChange = (event: Event) => {
|
onAnnotationDragStateChange = (event: Event) => {
|
||||||
if (!annotations) {
|
const annotation = findByAnnotationId(event.nativeEvent.annotationId);
|
||||||
return;
|
if (annotation) {
|
||||||
|
// Update location
|
||||||
|
annotation.latitude = event.nativeEvent.latitude;
|
||||||
|
annotation.longitude = event.nativeEvent.longitude;
|
||||||
|
// Call callback
|
||||||
|
annotation.onDragStateChange &&
|
||||||
|
annotation.onDragStateChange(event.nativeEvent);
|
||||||
}
|
}
|
||||||
// Find the annotation with the id that was pressed
|
};
|
||||||
for (let i = 0, l = annotations.length; i < l; i++) {
|
onAnnotationFocus = (event: Event) => {
|
||||||
let annotation = annotations[i];
|
const annotation = findByAnnotationId(event.nativeEvent.annotationId);
|
||||||
if (annotation.id === event.nativeEvent.annotationId) {
|
if (annotation && annotation.onFocus) {
|
||||||
// Update location
|
annotation.onFocus(event.nativeEvent);
|
||||||
annotation.latitude = event.nativeEvent.latitude;
|
|
||||||
annotation.longitude = event.nativeEvent.longitude;
|
|
||||||
// Call callback
|
|
||||||
annotation.onDragStateChange &&
|
|
||||||
annotation.onDragStateChange(event.nativeEvent);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
onAnnotationBlur = (event: Event) => {
|
||||||
|
const annotation = findByAnnotationId(event.nativeEvent.annotationId);
|
||||||
|
if (annotation && annotation.onBlur) {
|
||||||
|
annotation.onBlur(event.nativeEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: these should be separate events, to reduce bridge traffic
|
// TODO: these should be separate events, to reduce bridge traffic
|
||||||
@@ -451,6 +473,8 @@ const MapView = React.createClass({
|
|||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onAnnotationDragStateChange={onAnnotationDragStateChange}
|
onAnnotationDragStateChange={onAnnotationDragStateChange}
|
||||||
|
onAnnotationFocus={onAnnotationFocus}
|
||||||
|
onAnnotationBlur={onAnnotationBlur}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -484,6 +508,8 @@ MapView.PinColors = PinColors && {
|
|||||||
const RCTMap = requireNativeComponent('RCTMap', MapView, {
|
const RCTMap = requireNativeComponent('RCTMap', MapView, {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
onAnnotationDragStateChange: true,
|
onAnnotationDragStateChange: true,
|
||||||
|
onAnnotationFocus: true,
|
||||||
|
onAnnotationBlur: true,
|
||||||
onChange: true,
|
onChange: true,
|
||||||
onPress: true
|
onPress: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ RCT_EXTERN const CGFloat RCTMapZoomBoundBuffer;
|
|||||||
@property (nonatomic, copy) RCTBubblingEventBlock onChange;
|
@property (nonatomic, copy) RCTBubblingEventBlock onChange;
|
||||||
@property (nonatomic, copy) RCTBubblingEventBlock onPress;
|
@property (nonatomic, copy) RCTBubblingEventBlock onPress;
|
||||||
@property (nonatomic, copy) RCTBubblingEventBlock onAnnotationDragStateChange;
|
@property (nonatomic, copy) RCTBubblingEventBlock onAnnotationDragStateChange;
|
||||||
|
@property (nonatomic, copy) RCTBubblingEventBlock onAnnotationFocus;
|
||||||
|
@property (nonatomic, copy) RCTBubblingEventBlock onAnnotationBlur;
|
||||||
|
|
||||||
- (void)setAnnotations:(NSArray<RCTMapAnnotation *> *)annotations;
|
- (void)setAnnotations:(NSArray<RCTMapAnnotation *> *)annotations;
|
||||||
- (void)setOverlays:(NSArray<RCTMapOverlay *> *)overlays;
|
- (void)setOverlays:(NSArray<RCTMapOverlay *> *)overlays;
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ RCT_EXPORT_VIEW_PROPERTY(mapType, MKMapType)
|
|||||||
RCT_EXPORT_VIEW_PROPERTY(annotations, NSArray<RCTMapAnnotation *>)
|
RCT_EXPORT_VIEW_PROPERTY(annotations, NSArray<RCTMapAnnotation *>)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(overlays, NSArray<RCTMapOverlay *>)
|
RCT_EXPORT_VIEW_PROPERTY(overlays, NSArray<RCTMapOverlay *>)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onAnnotationDragStateChange, RCTBubblingEventBlock)
|
RCT_EXPORT_VIEW_PROPERTY(onAnnotationDragStateChange, RCTBubblingEventBlock)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(onAnnotationFocus, RCTBubblingEventBlock)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(onAnnotationBlur, RCTBubblingEventBlock)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
|
RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)
|
RCT_EXPORT_VIEW_PROPERTY(onPress, RCTBubblingEventBlock)
|
||||||
RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap)
|
RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap)
|
||||||
@@ -137,6 +139,7 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap)
|
|||||||
|
|
||||||
- (void)mapView:(RCTMap *)mapView didSelectAnnotationView:(MKAnnotationView *)view
|
- (void)mapView:(RCTMap *)mapView didSelectAnnotationView:(MKAnnotationView *)view
|
||||||
{
|
{
|
||||||
|
// TODO: Remove deprecated onAnnotationPress API call later.
|
||||||
if (mapView.onPress && [view.annotation isKindOfClass:[RCTMapAnnotation class]]) {
|
if (mapView.onPress && [view.annotation isKindOfClass:[RCTMapAnnotation class]]) {
|
||||||
RCTMapAnnotation *annotation = (RCTMapAnnotation *)view.annotation;
|
RCTMapAnnotation *annotation = (RCTMapAnnotation *)view.annotation;
|
||||||
mapView.onPress(@{
|
mapView.onPress(@{
|
||||||
@@ -150,6 +153,27 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ([view.annotation isKindOfClass:[RCTMapAnnotation class]]) {
|
||||||
|
RCTMapAnnotation *annotation = (RCTMapAnnotation *)view.annotation;
|
||||||
|
if (mapView.onAnnotationFocus) {
|
||||||
|
mapView.onAnnotationFocus(@{
|
||||||
|
@"annotationId": annotation.identifier
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mapView:(RCTMap *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
|
||||||
|
{
|
||||||
|
if ([view.annotation isKindOfClass:[RCTMapAnnotation class]]) {
|
||||||
|
RCTMapAnnotation *annotation = (RCTMapAnnotation *)view.annotation;
|
||||||
|
if (mapView.onAnnotationBlur) {
|
||||||
|
mapView.onAnnotationBlur(@{
|
||||||
|
@"annotationId": annotation.identifier
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mapView:(RCTMap *)mapView annotationView:(MKAnnotationView *)view
|
- (void)mapView:(RCTMap *)mapView annotationView:(MKAnnotationView *)view
|
||||||
|
|||||||
Reference in New Issue
Block a user