Skip to content

Commit

Permalink
Fix showCallout bug for pin views on ios
Browse files Browse the repository at this point in the history
  • Loading branch information
lelandrichardson committed Jan 23, 2016
1 parent bc23b43 commit fa74cfd
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 72 deletions.
28 changes: 14 additions & 14 deletions example/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,27 +65,27 @@ var App = React.createClass({


render() {
return this.renderExamples([
[DisplayLatLng, 'Tracking Position'],
[ViewsAsMarkers, 'Arbitrary Views as Markers'],
[EventListener, 'Events'],
[MarkerTypes, 'Image Based Markers'],
[DraggableMarkers, 'Draggable Markers'],
[PolygonCreator, 'Polygon Creator'],
[AnimatedViews, 'Animating with MapViews'],
[AnimatedMarkers, 'Animated Marker Position'],
[Callouts, 'Custom Callouts'],
[Overlays, 'Circles, Polygons, and Polylines'],
[DefaultMarkers, 'Default Markers'],
]);
//return this.renderExamples([
// [DisplayLatLng, 'Tracking Position'],
// [ViewsAsMarkers, 'Arbitrary Views as Markers'],
// [EventListener, 'Events'],
// [MarkerTypes, 'Image Based Markers'],
// [DraggableMarkers, 'Draggable Markers'],
// [PolygonCreator, 'Polygon Creator'],
// [AnimatedViews, 'Animating with MapViews'],
// [AnimatedMarkers, 'Animated Marker Position'],
// [Callouts, 'Custom Callouts'],
// [Overlays, 'Circles, Polygons, and Polylines'],
// [DefaultMarkers, 'Default Markers'],
//]);
//return <DisplayLatLng />;
//return <ViewsAsMarkers />;
//return <EventListener />;
//return <MarkerTypes />;
//return <DraggableMarkers />;
//return <PolygonCreator />;
//return <AnimatedViews />;
//return <Callouts />;
return <Callouts />;
//return <Overlays />;
//return <DefaultMarkers />;
},
Expand Down
20 changes: 19 additions & 1 deletion example/examples/Callouts.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ var Callouts = React.createClass({
};
},

show() {
this.refs.m1.showCallout();
},

hide() {
this.refs.m1.hideCallout();
},

render() {
const { region, markers } = this.state;
return (
Expand All @@ -63,18 +71,20 @@ var Callouts = React.createClass({
initialRegion={region}
>
<MapView.Marker
ref="m1"
coordinate={markers[0].coordinate}
title="This is a title"
description="This is a description"
/>
<MapView.Marker coordinate={markers[1].coordinate}>
<MapView.Marker ref="m2" coordinate={markers[1].coordinate}>
<MapView.Callout>
<View>
<Text>This is a plain view</Text>
</View>
</MapView.Callout>
</MapView.Marker>
<MapView.Marker
ref="m3"
coordinate={markers[2].coordinate}
calloutOffset={{ x: -8, y: 28 }}
calloutAnchor={{ x: 0.5, y: 0.4 }}
Expand All @@ -91,6 +101,14 @@ var Callouts = React.createClass({
<Text>Tap on markers to see different callouts</Text>
</View>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={this.show} style={[styles.bubble, styles.button]}>
<Text>Show</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.hide} style={[styles.bubble, styles.button]}>
<Text>Hide</Text>
</TouchableOpacity>
</View>
</View>
);
},
Expand Down
50 changes: 5 additions & 45 deletions ios/AirMaps/AIRMapManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -210,55 +210,15 @@ - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOv

- (void)mapView:(AIRMap *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if (![view.annotation isKindOfClass:[AIRMapMarker class]]) return;
AIRMapMarker *marker = (AIRMapMarker *)view.annotation;

id event = @{
@"action": @"marker-select",
@"id": marker.identifier ?: @"unknown",
@"coordinate": @{
@"latitude": @(marker.coordinate.latitude),
@"longitude": @(marker.coordinate.longitude)
}
};

if (mapView.onMarkerSelect) mapView.onMarkerSelect(event);
if (marker.onSelect) marker.onSelect(event);

if (![marker shouldShowCalloutView]) {
// no callout to show
return;
if ([view.annotation isKindOfClass:[AIRMapMarker class]]) {
[(AIRMapMarker *)view.annotation showCalloutView];
}

[marker fillCalloutView:mapView.calloutView];

// This is where we present our custom callout view... MapKit's built-in callout doesn't have the flexibility
// we need, but a lot of work was done by Nick Farina to make this identical to MapKit's built-in.
[mapView.calloutView presentCalloutFromRect:view.bounds
inView:view
constrainedToView:mapView
animated:YES];
}

- (void)mapView:(AIRMap *)mapView didDeselectAnnotationView:(MKAnnotationView *)view {
// hide the callout view
[mapView.calloutView dismissCalloutAnimated:YES];

if (![view.annotation isKindOfClass:[AIRMapMarker class]]) return;
AIRMapMarker *marker = (AIRMapMarker *)view.annotation;

id event = @{
@"action": @"marker-deselect",
@"id": marker.identifier ?: @"unknown",
@"coordinate": @{
@"latitude": @(marker.coordinate.latitude),
@"longitude": @(marker.coordinate.longitude)
}
};

if (mapView.onMarkerDeselect) mapView.onMarkerDeselect(event);
if (marker.onDeselect) marker.onDeselect(event);

if ([view.annotation isKindOfClass:[AIRMapMarker class]]) {
[(AIRMapMarker *)view.annotation hideCalloutView];
}
}

- (MKAnnotationView *)mapView:(__unused AIRMap *)mapView viewForAnnotation:(AIRMapMarker *)marker
Expand Down
2 changes: 2 additions & 0 deletions ios/AirMaps/AIRMapMarker.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
- (MKAnnotationView *)getAnnotationView;
- (void)fillCalloutView:(SMCalloutView *)calloutView;
- (BOOL)shouldShowCalloutView;
- (void)showCalloutView;
- (void)hideCalloutView;

@end

Expand Down
69 changes: 63 additions & 6 deletions ios/AirMaps/AIRMapMarker.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ @implementation EmptyCalloutBackgroundView
@implementation AIRMapMarker {
BOOL _hasSetCalloutOffset;
RCTImageLoaderCancellationBlock _reloadImageCancellationBlock;
MKPinAnnotationView *_pinView;
}

- (void)reactSetFrame:(CGRect)frame
Expand Down Expand Up @@ -66,18 +67,21 @@ - (MKAnnotationView *)getAnnotationView
{
if ([self shouldUsePinView]) {
// In this case, we want to render a platform "default" marker.
MKPinAnnotationView *view = [MKPinAnnotationView new];
view.annotation = self;
view.draggable = self.draggable;
if (_pinView == nil) {
_pinView = [MKPinAnnotationView new];
_pinView.annotation = self;
}

_pinView.draggable = self.draggable;

// TODO(lmr): Looks like this API was introduces in iOS 8. We may want to handle differently for earlier
// versions. Right now it's just leaving it with the default color. People needing the colors are free to
// use their own custom markers.
if ([view respondsToSelector:@selector(setPinTintColor:)]) {
view.pinTintColor = self.pinColor;
if ([_pinView respondsToSelector:@selector(setPinTintColor:)]) {
_pinView.pinTintColor = self.pinColor;
}

return view;
return _pinView;
} else {
// If it has subviews, it means we are wanting to render a custom marker with arbitrary react views.
// if it has a non-null image, it means we want to render a custom marker with the image.
Expand Down Expand Up @@ -126,6 +130,59 @@ - (void)fillCalloutView:(SMCalloutView *)calloutView
}
}

- (void)showCalloutView
{
MKAnnotationView *annotationView = [self getAnnotationView];

[self setSelected:YES animated:NO];

id event = @{
@"action": @"marker-select",
@"id": self.identifier ?: @"unknown",
@"coordinate": @{
@"latitude": @(self.coordinate.latitude),
@"longitude": @(self.coordinate.longitude)
}
};

if (self.map.onMarkerSelect) self.map.onMarkerSelect(event);
if (self.onSelect) self.onSelect(event);

if (![self shouldShowCalloutView]) {
// no callout to show
return;
}

[self fillCalloutView:self.map.calloutView];

// This is where we present our custom callout view... MapKit's built-in callout doesn't have the flexibility
// we need, but a lot of work was done by Nick Farina to make this identical to MapKit's built-in.
[self.map.calloutView presentCalloutFromRect:annotationView.bounds
inView:annotationView
constrainedToView:self.map
animated:YES];
}

- (void)hideCalloutView
{
// hide the callout view
[self.map.calloutView dismissCalloutAnimated:YES];

[self setSelected:NO animated:NO];

id event = @{
@"action": @"marker-deselect",
@"id": self.identifier ?: @"unknown",
@"coordinate": @{
@"latitude": @(self.coordinate.latitude),
@"longitude": @(self.coordinate.longitude)
}
};

if (self.map.onMarkerDeselect) self.map.onMarkerDeselect(event);
if (self.onDeselect) self.onDeselect(event);
}

- (void)setCalloutOffset:(CGPoint)calloutOffset
{
_hasSetCalloutOffset = YES;
Expand Down
8 changes: 2 additions & 6 deletions ios/AirMaps/AIRMapMarkerManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ - (UIView *)view
if (![view isKindOfClass:[AIRMapMarker class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
} else {
AIRMapMarker *marker = (AIRMapMarker *)view;

[marker setSelected:YES animated:YES];
[(AIRMapMarker *) view showCalloutView];
}
}];
}
Expand All @@ -74,9 +72,7 @@ - (UIView *)view
if (![view isKindOfClass:[AIRMapMarker class]]) {
RCTLogError(@"Invalid view returned from registry, expecting AIRMap, got: %@", view);
} else {
AIRMapMarker *marker = (AIRMapMarker *)view;

[marker setSelected:NO animated:YES];
[(AIRMapMarker *) view hideCalloutView];
}
}];
}
Expand Down

0 comments on commit fa74cfd

Please sign in to comment.