Skip to content

Commit

Permalink
Merge pull request #50 from bsudekum/rightcallout
Browse files Browse the repository at this point in the history
Add rightCalloutAccessory
  • Loading branch information
Bobby Sudekum committed Jun 20, 2015
2 parents abba1c6 + 83c5dc5 commit 659db4b
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 21 deletions.
53 changes: 51 additions & 2 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
| `rotateEnabled` | `bool` | Optional | `true` | Whether the map can rotate |
|`showsUserLocation` | `bool` | Optional | `false` | Whether the user's location is shown on the map. Note - the map will not zoom to their location.|
| `styleURL` | `string` | Optional | Mapbox Streets | A Mapbox GL style sheet. Defaults to `mapbox-streets`. More styles [can be viewed here](https://www.mapbox.com/mapbox-gl-styles).
| `annotations` | `array` | Optional | NA | An array of annotation objects. `latitude`/`longitude` are required, both `title` and `subtitle` are optional.
| `annotations` | `array` | Optional | NA | An array of annotation objects. See [annotation detail](https://github.com/bsudekum/react-native-mapbox-gl/blob/master/API.md#annotations)
| `direction` | `double` | Optional | `0` | Heading of the map in degrees where 0 is north and 180 is south |
| `debugActive` | `bool` | Optional | `false` | Turns on debug mode. |
| `style` | flexbox `view` | Optional | NA | Styles the actual map view container |
Expand All @@ -33,7 +33,7 @@ These methods require you to use `MapboxGLMap.Mixin` to access the methods. Each
| `setZoomLevelAnimated` | `mapViewRef`, `zoomLevel` | Zooms the map to a new zoom level
| `setCenterCoordinateAnimated` | `mapViewRef`, `latitude`, `longitude` | Moves the map to a new coordinate. Note, the zoom level stay at the current zoom level
| `setCenterCoordinateZoomLevelAnimated` | `mapViewRef`, `latitude`, `longitude`, `zoomLevel` | Moves the map to a new coordinate and zoom level
| `addAnnotations` | `mapViewRef`, `[{latitude: number, longitude: number, title: string, subtitle: string}]` (array of objects) | Adds an annotation to the map without redrawing the map. Note, this will remove all previous annotations from the map.
| `addAnnotations` | `mapViewRef`, `[{latitude: number, longitude: number, title: string, subtitle: string, id: string, rightCalloutAccessory: { url: string, height: int, width: int }}]` (array of objects) | Adds an annotation to the map without redrawing the map. Note, this will remove all previous annotations from the map.
| `selectAnnotationAnimated` | `mapViewRef`, `annotationPlaceInArray` | Open the callout of the selected annotation. This method works with the current annotations on the map. `annotationPlaceInArray` starts at 0 and refers to the first annotation.
| `removeAnnotation` | `mapViewRef`, `annotationPlaceInArray` | Removes the selected annotation from the map. This method works with the current annotations on the map. `annotationPlaceInArray` starts at 0 and refers to the first annotation.

Expand All @@ -49,3 +49,52 @@ You can change the `styleURL` to any valid GL stylesheet, here are a few:
* `asset://styles/mapbox-streets-v7.json`
* `asset://styles/outdoors-v7.json`
* `asset://styles/satellite-v7.json`

## Annotations
```json
[{
"latitude": "required",
"longitude": "required",
"title": "optional string",
"subtitle": "optional string",
"id": "optional string, unique identifier.",
"rightCalloutAccessory": {
"url": "Optional. Either remote image or specify via 'image!yourImage.png'",
"height": "required if url specified",
"width": "required if url specified",
}
}]
```
**For adding local images via `image!yourImage.png` see [adding static resources to your app using Images.xcassets docs](https://facebook.github.io/react-native/docs/image.html#adding-static-resources-to-your-app-using-images-xcassets)**.

#### Example
```json
annotations: [{
"latitude": 40.72052634,
"longitude": -73.94686958312988,
"title": "This is a title",
"subtitle": "this is a subtitle",
"id": "foobar1234",
"rightCalloutAccessory": {
"url": "image!myIcon.jpg",
"height": 30,
"width": 30
}
}, {
"latitude": 40.72052634,
"longitude": -73.95686958312988,
"title": "This is another title",
"subtitle": "this is a subtitle",
"id": "010101",
"rightCalloutAccessory": {
"url": "http://png-3.findicons.com/files/icons/2799/flat_icons/256/gear.png",
"height": 30,
"width": 30
}
}, {
"latitude": 40.82052634,
"longitude": -73.85686958312988,
"title": "This is another title",
"subtitle": "this is a subtitle"
}]
```
16 changes: 15 additions & 1 deletion RCTMapboxGL.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ var MapView = React.createClass({
}
this.props.onOpenAnnotation(event.nativeEvent.annotation);
},
_onRightAnnotationTapped(event: Event) {
if (!this.props.onRightAnnotationTapped) {
return;
}
this.props.onRightAnnotationTapped(event.nativeEvent.annotation);
},
_onUpdateUserLocation(event: Event) {
if (!this.props.onUpdateUserLocation) {
return;
Expand All @@ -69,11 +75,18 @@ var MapView = React.createClass({
longitude: React.PropTypes.number.isRequired,
title: React.PropTypes.string,
subtitle: React.PropTypes.string,
id: React.PropTypes.string,
rightCalloutAccessory: React.PropTypes.object({
height: React.PropTypes.number,
width: React.PropTypes.number,
url: React.PropTypes.string,
})
})),
onRegionChange: React.PropTypes.func,
onRegionWillChange: React.PropTypes.func,
onOpenAnnotation: React.PropTypes.func,
onUpdateUserLocation: React.PropTypes.func
onUpdateUserLocation: React.PropTypes.func,
onRightAnnotationTapped: React.PropTypes.func
},

render: function() {
Expand All @@ -88,6 +101,7 @@ var MapView = React.createClass({
{...props}
onChange={this._onChange}
onBlur={this._onOpenAnnotation}
topTap={this._onRightAnnotationTapped}
onLoadingFinish={this._onUpdateUserLocation} />;
}
});
Expand Down
13 changes: 10 additions & 3 deletions RCTMapboxGL/RCTMapboxGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;

- (void)setAccessToken:(NSString *)accessToken;
- (void)setAnnotations:(NSMutableDictionary *)annotations;
- (void)setAnnotations:(NSArray *)annotations;
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate;
- (void)setClipsToBounds:(BOOL)clipsToBounds;
- (void)setDebugActive:(BOOL)debugActive;
Expand All @@ -37,9 +37,16 @@

@interface RCTMGLAnnotation : NSObject <MGLAnnotation>

+ (instancetype)annotationWithLocation:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle;
@property (nonatomic, strong) UIButton *rightCalloutAccessory;
@property (nonatomic) NSString *id;

- (instancetype)initWithLocation:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle;
+ (instancetype)annotationWithLocation:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle id:(NSString *)id;

+ (instancetype)annotationWithLocationRightCallout:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle id:(NSString *)id rightCalloutAccessory:(UIButton *)rightCalloutAccessory;

- (instancetype)initWithLocation:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle id:(NSString *)id;

- (instancetype)initWithLocationRightCallout:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle id:(NSString *)id rightCalloutAccessory:(UIButton *)rightCalloutAccessory;


@end
81 changes: 72 additions & 9 deletions RCTMapboxGL/RCTMapboxGL.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import "RCTBridgeModule.h"
#import "RCTEventDispatcher.h"
#import "UIView+React.h"
#import "RCTLog.h"

@implementation RCTMapboxGL {
/* Required to publish events */
Expand All @@ -31,6 +32,7 @@ @implementation RCTMapboxGL {
BOOL _showsUserLocation;
NSURL *_styleURL;
double _zoomLevel;
UIButton *_rightCalloutAccessory;
}

RCT_EXPORT_MODULE();
Expand Down Expand Up @@ -160,6 +162,12 @@ - (void)setStyleURL:(NSURL*)styleURL
[self updateMap];
}

- (void)setRightCalloutAccessory:(UIButton *)rightCalloutAccessory
{
_rightCalloutAccessory = rightCalloutAccessory;
[self performSelector:@selector(updateAnnotations) withObject:nil afterDelay:0.1];
}

-(void)setDirectionAnimated:(int)heading
{
[_map setDirection:heading animated:YES];
Expand Down Expand Up @@ -197,9 +205,13 @@ - (void)mapView:(MGLMapView *)mapView didUpdateUserLocation:(MGLUserLocation *)u
-(void)mapView:(MGLMapView *)mapView didSelectAnnotation:(id<MGLAnnotation>)annotation
{
if (annotation.title && annotation.subtitle) {

NSString *id = [(RCTMGLAnnotation *) annotation id];

NSDictionary *event = @{ @"target": self.reactTag,
@"annotation": @{ @"title": annotation.title,
@"subtitle": annotation.subtitle,
@"id": id,
@"latitude": @(annotation.coordinate.latitude),
@"longitude": @(annotation.coordinate.longitude)} };

Expand All @@ -221,6 +233,7 @@ - (void)mapView:(RCTMapboxGL *)mapView regionDidChangeAnimated:(BOOL)animated
[_eventDispatcher sendInputEventWithName:@"topChange" body:event];
}


- (void)mapView:(RCTMapboxGL *)mapView regionWillChangeAnimated:(BOOL)animated
{

Expand All @@ -240,23 +253,52 @@ - (BOOL)mapView:(RCTMapboxGL *)mapView annotationCanShowCallout:(id <MGLAnnotati

- (void)selectAnnotationAnimated:(NSUInteger)annotationInArray
{
if ([_annotations count] <= annotationInArray) NSAssert(NO, @"Could not find annotation in array.");
if ([_annotations count] != 0)
{
if (annotationInArray >= [_annotations count]) {
RCTLogError(@"Could not find annotation in array");
return;
}
if ([_annotations count] != 0) {
[_map selectAnnotation:_annotations[annotationInArray] animated:YES];
}
}

- (void)removeAnnotation:(NSUInteger)annotationInArray
{
if ([_annotations count] <= annotationInArray) NSAssert(NO, @"Could not find annotation in array.");
if ([_annotations count] != 0)
{
if (annotationInArray >= [_annotations count]) {
RCTLogError(@"Could not find annotation in array");
return;
}
if ([_annotations count] != 0) {
[_map removeAnnotation:_annotations[annotationInArray]];
[_annotations removeObjectAtIndex:annotationInArray];
}
}

- (UIButton *)mapView:(MGLMapView *)mapView rightCalloutAccessoryViewForAnnotation:(id <MGLAnnotation>)annotation;
{
if ([annotation isKindOfClass:[RCTMGLAnnotation class]]) {
UIButton *accessoryButton = [(RCTMGLAnnotation *) annotation rightCalloutAccessory];
return accessoryButton;
}
return nil;
}

- (void)mapView:(MGLMapView *)mapView annotation:(id<MGLAnnotation>)annotation calloutAccessoryControlTapped:(UIControl *)control
{
if (annotation.title && annotation.subtitle) {

NSString *id = [(RCTMGLAnnotation *) annotation id];

NSDictionary *event = @{ @"target": self.reactTag,
@"annotation": @{ @"title": annotation.title,
@"subtitle": annotation.subtitle,
@"id": id,
@"latitude": @(annotation.coordinate.latitude),
@"longitude": @(annotation.coordinate.longitude)} };

[_eventDispatcher sendInputEventWithName:@"topBlur" body:event];
}
}
@end

/* RCTMGLAnnotation */
Expand All @@ -271,17 +313,38 @@ @interface RCTMGLAnnotation ()

@implementation RCTMGLAnnotation

+ (instancetype)annotationWithLocation:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle
+ (instancetype)annotationWithLocation:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle id:(NSString *)id
{
return [[self alloc] initWithLocation:coordinate title:title subtitle:subtitle id:id];
}

+ (instancetype)annotationWithLocationRightCallout:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle id:(NSString *)id rightCalloutAccessory:(UIButton *)rightCalloutAccessory
{
return [[self alloc] initWithLocationRightCallout:coordinate title:title subtitle:subtitle id:id rightCalloutAccessory:rightCalloutAccessory];
}


- (instancetype)initWithLocation:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle id:(NSString *)id
{
return [[self alloc] initWithLocation:coordinate title:title subtitle:subtitle];
if (self = [super init]) {
_coordinate = coordinate;
_title = title;
_subtitle = subtitle;
_id = id;
}

return self;
}

- (instancetype)initWithLocation:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle

- (instancetype)initWithLocationRightCallout:(CLLocationCoordinate2D)coordinate title:(NSString *)title subtitle:(NSString *)subtitle id:(NSString *)id rightCalloutAccessory:(UIButton *)rightCalloutAccessory
{
if (self = [super init]) {
_rightCalloutAccessory = rightCalloutAccessory;
_coordinate = coordinate;
_title = title;
_subtitle = subtitle;
_id = id;
}

return self;
Expand Down
Loading

0 comments on commit 659db4b

Please sign in to comment.