[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.

![screen shot 2015-05-12 at 10 07 43 pm](https://cloud.githubusercontent.com/assets/688326/7588677/8479a7a4-f8f9-11e4-99a4-1dc3c7691810.png)

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:
David Mohl
2015-06-25 09:07:19 -07:00
parent 3c5b4b0a9f
commit 99bc08cf61
13 changed files with 313 additions and 54 deletions

View File

@@ -15,6 +15,9 @@
#import "RCTEventDispatcher.h"
#import "RCTMap.h"
#import "UIView+React.h"
#import "RCTPointAnnotation.h"
#import <MapKit/MapKit.h>
static NSString *const RCTMapViewKey = @"MapView";
@@ -42,7 +45,7 @@ RCT_EXPORT_VIEW_PROPERTY(maxDelta, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(minDelta, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(legalLabelInsets, UIEdgeInsets)
RCT_EXPORT_VIEW_PROPERTY(mapType, MKMapType)
RCT_EXPORT_VIEW_PROPERTY(annotations, MKShapeArray)
RCT_EXPORT_VIEW_PROPERTY(annotations, RCTPointAnnotationArray)
RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap)
{
[view setRegion:json ? [RCTConvert MKCoordinateRegion:json] : defaultView.region animated:YES];
@@ -50,6 +53,73 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap)
#pragma mark MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if (![view.annotation isKindOfClass:[MKUserLocation class]]) {
RCTPointAnnotation *annotation = (RCTPointAnnotation *)view.annotation;
NSString *title = view.annotation.title ?: @"";
NSString *subtitle = view.annotation.subtitle ?: @"";
NSDictionary *event = @{
@"target": mapView.reactTag,
@"action": @"annotation-click",
@"annotation": @{
@"id": annotation.identifier,
@"title": title,
@"subtitle": subtitle,
@"latitude": @(annotation.coordinate.latitude),
@"longitude": @(annotation.coordinate.longitude)
}
};
[self.bridge.eventDispatcher sendInputEventWithName:@"topTap" body:event];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(RCTPointAnnotation *)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
MKPinAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"RCTAnnotation"];
annotationView.canShowCallout = true;
annotationView.animatesDrop = annotation.animateDrop;
annotationView.leftCalloutAccessoryView = nil;
if (annotation.hasLeftCallout) {
annotationView.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
annotationView.rightCalloutAccessoryView = nil;
if (annotation.hasRightCallout) {
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
return annotationView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
// Pass to js
RCTPointAnnotation *annotation = (RCTPointAnnotation *)view.annotation;
NSString *side = (control == view.leftCalloutAccessoryView) ? @"left" : @"right";
NSDictionary *event = @{
@"target": mapView.reactTag,
@"side": side,
@"action": @"callout-click",
@"annotationId": annotation.identifier
};
[self.bridge.eventDispatcher sendInputEventWithName:@"topTap" body:event];
}
- (void)mapView:(RCTMap *)mapView didUpdateUserLocation:(MKUserLocation *)location
{
if (mapView.followUserLocation) {
@@ -143,7 +213,7 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap)
#define FLUSH_NAN(value) (isnan(value) ? 0 : value)
NSDictionary *event = @{
@"target": [mapView reactTag],
@"target": mapView.reactTag,
@"continuous": @(continuous),
@"region": @{
@"latitude": @(FLUSH_NAN(region.center.latitude)),