@lugg/maps 1.0.0-beta.0 → 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +74 -0
- package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +38 -0
- package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +0 -11
- package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +73 -51
- package/android/src/main/java/com/luggmaps/LuggPackage.kt +8 -1
- package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +181 -5
- package/ios/LuggCalloutView.h +23 -0
- package/ios/LuggCalloutView.mm +145 -0
- package/ios/LuggMarkerView.h +2 -0
- package/ios/LuggMarkerView.mm +17 -2
- package/ios/core/AppleMapProvider.mm +152 -8
- package/ios/core/GoogleMapProvider.mm +114 -5
- package/ios/core/LuggAnnotationView.h +12 -0
- package/ios/core/LuggAnnotationView.mm +55 -0
- package/lib/module/MapProvider.web.js +3 -1
- package/lib/module/MapProvider.web.js.map +1 -1
- package/lib/module/MapView.web.js +15 -2
- package/lib/module/MapView.web.js.map +1 -1
- package/lib/module/components/Marker.js +21 -4
- package/lib/module/components/Marker.js.map +1 -1
- package/lib/module/components/Marker.web.js +86 -22
- package/lib/module/components/Marker.web.js.map +1 -1
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +20 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/MapProvider.web.d.ts +6 -0
- package/lib/typescript/src/MapProvider.web.d.ts.map +1 -1
- package/lib/typescript/src/MapView.web.d.ts.map +1 -1
- package/lib/typescript/src/components/GeoJson.types.d.ts +11 -1
- package/lib/typescript/src/components/GeoJson.types.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.d.ts +1 -1
- package/lib/typescript/src/components/Marker.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.types.d.ts +27 -1
- package/lib/typescript/src/components/Marker.types.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
- package/lib/typescript/src/components/index.d.ts +1 -1
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/lib/typescript/src/components/index.web.d.ts +1 -1
- package/lib/typescript/src/components/index.web.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +13 -0
- package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +2 -2
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/MapProvider.web.tsx +11 -1
- package/src/MapView.web.tsx +26 -2
- package/src/components/GeoJson.types.ts +12 -1
- package/src/components/Marker.tsx +29 -1
- package/src/components/Marker.types.ts +28 -1
- package/src/components/Marker.web.tsx +113 -23
- package/src/components/index.ts +1 -0
- package/src/components/index.web.ts +1 -1
- package/src/fabric/LuggCalloutViewNativeComponent.ts +20 -0
- package/src/index.ts +2 -0
- package/src/index.web.ts +2 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#import <React/RCTViewComponentView.h>
|
|
2
|
+
#import <UIKit/UIKit.h>
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
|
|
6
|
+
@class LuggCalloutView;
|
|
7
|
+
|
|
8
|
+
@protocol LuggCalloutViewDelegate <NSObject>
|
|
9
|
+
@optional
|
|
10
|
+
- (void)calloutViewDidUpdate:(LuggCalloutView *)calloutView;
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
@interface LuggCalloutView : RCTViewComponentView
|
|
14
|
+
|
|
15
|
+
@property(nonatomic, readonly) BOOL bubbled;
|
|
16
|
+
@property(nonatomic, readonly) CGPoint anchor;
|
|
17
|
+
@property(nonatomic, readonly) BOOL hasCustomContent;
|
|
18
|
+
@property(nonatomic, readonly) UIView *contentView;
|
|
19
|
+
@property(nonatomic, weak, nullable) id<LuggCalloutViewDelegate> delegate;
|
|
20
|
+
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#import "LuggCalloutView.h"
|
|
2
|
+
|
|
3
|
+
#import <react/renderer/components/RNMapsSpec/ComponentDescriptors.h>
|
|
4
|
+
#import <react/renderer/components/RNMapsSpec/Props.h>
|
|
5
|
+
#import <react/renderer/components/RNMapsSpec/RCTComponentViewHelpers.h>
|
|
6
|
+
|
|
7
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
8
|
+
|
|
9
|
+
using namespace facebook::react;
|
|
10
|
+
|
|
11
|
+
@interface LuggCalloutContentView : UIView
|
|
12
|
+
- (void)updateContentSize;
|
|
13
|
+
@end
|
|
14
|
+
|
|
15
|
+
@implementation LuggCalloutContentView
|
|
16
|
+
|
|
17
|
+
- (CGSize)intrinsicContentSize {
|
|
18
|
+
CGFloat width = 0;
|
|
19
|
+
CGFloat height = 0;
|
|
20
|
+
for (UIView *subview in self.subviews) {
|
|
21
|
+
width = MAX(width, CGRectGetMaxX(subview.frame));
|
|
22
|
+
height = MAX(height, CGRectGetMaxY(subview.frame));
|
|
23
|
+
}
|
|
24
|
+
if (width > 0 && height > 0) {
|
|
25
|
+
return CGSizeMake(width, height);
|
|
26
|
+
}
|
|
27
|
+
return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
- (void)updateContentSize {
|
|
31
|
+
CGSize size = [self intrinsicContentSize];
|
|
32
|
+
if (size.width > 0 && size.height > 0) {
|
|
33
|
+
self.frame = CGRectMake(0, 0, size.width, size.height);
|
|
34
|
+
}
|
|
35
|
+
[self invalidateIntrinsicContentSize];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@end
|
|
39
|
+
|
|
40
|
+
@interface LuggCalloutView () <RCTLuggCalloutViewViewProtocol>
|
|
41
|
+
@end
|
|
42
|
+
|
|
43
|
+
@implementation LuggCalloutView {
|
|
44
|
+
LuggCalloutContentView *_contentView;
|
|
45
|
+
BOOL _bubbled;
|
|
46
|
+
CGPoint _anchor;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
50
|
+
return concreteComponentDescriptorProvider<
|
|
51
|
+
LuggCalloutViewComponentDescriptor>();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (instancetype)initWithFrame:(CGRect)frame {
|
|
55
|
+
if (self = [super initWithFrame:frame]) {
|
|
56
|
+
static const auto defaultProps =
|
|
57
|
+
std::make_shared<const LuggCalloutViewProps>();
|
|
58
|
+
_props = defaultProps;
|
|
59
|
+
|
|
60
|
+
_bubbled = YES;
|
|
61
|
+
_anchor = CGPointMake(0.5, 1.0);
|
|
62
|
+
_contentView = [[LuggCalloutContentView alloc] init];
|
|
63
|
+
_contentView.backgroundColor = [UIColor clearColor];
|
|
64
|
+
|
|
65
|
+
self.backgroundColor = [UIColor clearColor];
|
|
66
|
+
self.hidden = YES;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return self;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
- (void)updateProps:(const Props::Shared &)props
|
|
73
|
+
oldProps:(const Props::Shared &)oldProps {
|
|
74
|
+
const auto &newViewProps =
|
|
75
|
+
*std::static_pointer_cast<LuggCalloutViewProps const>(props);
|
|
76
|
+
|
|
77
|
+
_bubbled = newViewProps.bubbled;
|
|
78
|
+
|
|
79
|
+
if (oldProps) {
|
|
80
|
+
const auto &oldViewProps =
|
|
81
|
+
*std::static_pointer_cast<LuggCalloutViewProps const>(oldProps);
|
|
82
|
+
if (newViewProps.anchor.x != oldViewProps.anchor.x ||
|
|
83
|
+
newViewProps.anchor.y != oldViewProps.anchor.y) {
|
|
84
|
+
_anchor = CGPointMake(newViewProps.anchor.x, newViewProps.anchor.y);
|
|
85
|
+
}
|
|
86
|
+
} else if (newViewProps.anchor.x != 0 || newViewProps.anchor.y != 0) {
|
|
87
|
+
_anchor = CGPointMake(newViewProps.anchor.x, newViewProps.anchor.y);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
[super updateProps:props oldProps:oldProps];
|
|
91
|
+
[_delegate calloutViewDidUpdate:self];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
- (BOOL)bubbled {
|
|
95
|
+
return _bubbled;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
- (CGPoint)anchor {
|
|
99
|
+
return _anchor;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
- (void)mountChildComponentView:
|
|
103
|
+
(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
104
|
+
index:(NSInteger)index {
|
|
105
|
+
[_contentView insertSubview:childComponentView atIndex:index];
|
|
106
|
+
[_contentView updateContentSize];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
- (void)unmountChildComponentView:
|
|
110
|
+
(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
111
|
+
index:(NSInteger)index {
|
|
112
|
+
[childComponentView removeFromSuperview];
|
|
113
|
+
[_contentView updateContentSize];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
- (void)layoutSubviews {
|
|
117
|
+
[super layoutSubviews];
|
|
118
|
+
CGSize oldSize = _contentView.bounds.size;
|
|
119
|
+
[_contentView updateContentSize];
|
|
120
|
+
CGSize newSize = _contentView.bounds.size;
|
|
121
|
+
if (!CGSizeEqualToSize(oldSize, newSize)) {
|
|
122
|
+
[_delegate calloutViewDidUpdate:self];
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
- (BOOL)hasCustomContent {
|
|
127
|
+
return _contentView.subviews.count > 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
- (UIView *)contentView {
|
|
131
|
+
return _contentView;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
- (void)prepareForRecycle {
|
|
135
|
+
[super prepareForRecycle];
|
|
136
|
+
for (UIView *subview in _contentView.subviews) {
|
|
137
|
+
[subview removeFromSuperview];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
Class<RCTComponentViewProtocol> LuggCalloutViewCls(void) {
|
|
142
|
+
return LuggCalloutView.class;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@end
|
package/ios/LuggMarkerView.h
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
NS_ASSUME_NONNULL_BEGIN
|
|
6
6
|
|
|
7
7
|
@class LuggMarkerView;
|
|
8
|
+
@class LuggCalloutView;
|
|
8
9
|
|
|
9
10
|
@protocol LuggMarkerViewDelegate <NSObject>
|
|
10
11
|
@optional
|
|
@@ -27,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
27
28
|
@property(nonatomic, readonly) BOOL hasCustomView;
|
|
28
29
|
@property(nonatomic, readonly) BOOL didLayout;
|
|
29
30
|
@property(nonatomic, readonly) UIView *iconView;
|
|
31
|
+
@property(nonatomic, readonly, nullable) LuggCalloutView *calloutView;
|
|
30
32
|
@property(nonatomic, weak, nullable) id<LuggMarkerViewDelegate> delegate;
|
|
31
33
|
@property(nonatomic, strong, nullable) NSObject *marker;
|
|
32
34
|
|
package/ios/LuggMarkerView.mm
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import "LuggMarkerView.h"
|
|
2
|
+
#import "LuggCalloutView.h"
|
|
2
3
|
#import "events/MarkerDragEvent.h"
|
|
3
4
|
#import "events/MarkerPressEvent.h"
|
|
4
5
|
|
|
@@ -28,6 +29,7 @@ using namespace luggmaps::events;
|
|
|
28
29
|
BOOL _draggable;
|
|
29
30
|
BOOL _didLayout;
|
|
30
31
|
UIView *_iconView;
|
|
32
|
+
LuggCalloutView *_calloutView;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
@@ -92,14 +94,22 @@ using namespace luggmaps::events;
|
|
|
92
94
|
- (void)mountChildComponentView:
|
|
93
95
|
(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
94
96
|
index:(NSInteger)index {
|
|
95
|
-
[
|
|
97
|
+
if ([childComponentView isKindOfClass:[LuggCalloutView class]]) {
|
|
98
|
+
_calloutView = (LuggCalloutView *)childComponentView;
|
|
99
|
+
} else {
|
|
100
|
+
[_iconView insertSubview:childComponentView atIndex:index];
|
|
101
|
+
}
|
|
96
102
|
_didLayout = NO;
|
|
97
103
|
}
|
|
98
104
|
|
|
99
105
|
- (void)unmountChildComponentView:
|
|
100
106
|
(UIView<RCTComponentViewProtocol> *)childComponentView
|
|
101
107
|
index:(NSInteger)index {
|
|
102
|
-
[childComponentView
|
|
108
|
+
if ([childComponentView isKindOfClass:[LuggCalloutView class]]) {
|
|
109
|
+
_calloutView = nil;
|
|
110
|
+
} else {
|
|
111
|
+
[childComponentView removeFromSuperview];
|
|
112
|
+
}
|
|
103
113
|
_didLayout = NO;
|
|
104
114
|
}
|
|
105
115
|
|
|
@@ -180,6 +190,10 @@ using namespace luggmaps::events;
|
|
|
180
190
|
return _iconView;
|
|
181
191
|
}
|
|
182
192
|
|
|
193
|
+
- (LuggCalloutView *)calloutView {
|
|
194
|
+
return _calloutView;
|
|
195
|
+
}
|
|
196
|
+
|
|
183
197
|
- (UIImage *)createIconImage {
|
|
184
198
|
CGSize size = _iconView.bounds.size;
|
|
185
199
|
if (size.width <= 0 || size.height <= 0) {
|
|
@@ -271,6 +285,7 @@ using namespace luggmaps::events;
|
|
|
271
285
|
- (void)prepareForRecycle {
|
|
272
286
|
[super prepareForRecycle];
|
|
273
287
|
_didLayout = NO;
|
|
288
|
+
_calloutView = nil;
|
|
274
289
|
self.marker = nil;
|
|
275
290
|
self.delegate = nil;
|
|
276
291
|
[self resetIconViewTransform];
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#import "AppleMapProvider.h"
|
|
2
|
+
#import "../LuggCalloutView.h"
|
|
2
3
|
#import "../LuggMarkerView.h"
|
|
3
4
|
#import "../LuggPolygonView.h"
|
|
4
5
|
#import "../LuggPolylineView.h"
|
|
5
6
|
#import "../extensions/MKMapView+Zoom.h"
|
|
7
|
+
#import "LuggAnnotationView.h"
|
|
6
8
|
#import "MKPolylineAnimator.h"
|
|
7
9
|
|
|
8
10
|
@interface AppleMarkerAnnotation : NSObject <MKAnnotation>
|
|
@@ -20,11 +22,12 @@
|
|
|
20
22
|
@end
|
|
21
23
|
|
|
22
24
|
@interface AppleMapProvider () <
|
|
23
|
-
LuggMarkerViewDelegate,
|
|
24
|
-
UIGestureRecognizerDelegate>
|
|
25
|
+
LuggMarkerViewDelegate, LuggCalloutViewDelegate, LuggPolylineViewDelegate,
|
|
26
|
+
LuggPolygonViewDelegate, UIGestureRecognizerDelegate>
|
|
25
27
|
@end
|
|
26
28
|
|
|
27
29
|
@implementation AppleMapProvider {
|
|
30
|
+
UIView *_wrapperView;
|
|
28
31
|
LuggAppleMapViewContent *_mapView;
|
|
29
32
|
BOOL _isMapReady;
|
|
30
33
|
BOOL _isDragging;
|
|
@@ -34,6 +37,8 @@
|
|
|
34
37
|
NSMapTable<id<MKOverlay>, LuggPolygonView *> *_overlayToPolygonMap;
|
|
35
38
|
UITapGestureRecognizer *_tapGesture;
|
|
36
39
|
UILongPressGestureRecognizer *_longPressGesture;
|
|
40
|
+
LuggMarkerView *_activeNonBubbledMarker;
|
|
41
|
+
BOOL _isReselectingAnnotation;
|
|
37
42
|
// Edge insets animation
|
|
38
43
|
CADisplayLink *_edgeInsetsDisplayLink;
|
|
39
44
|
UIEdgeInsets _edgeInsetsFrom;
|
|
@@ -91,6 +96,7 @@
|
|
|
91
96
|
|
|
92
97
|
[_tapGesture requireGestureRecognizerToFail:_longPressGesture];
|
|
93
98
|
|
|
99
|
+
_wrapperView = wrapperView;
|
|
94
100
|
[wrapperView addSubview:_mapView];
|
|
95
101
|
|
|
96
102
|
MKCoordinateRegion region = [_mapView regionForCenterCoordinate:coordinate
|
|
@@ -103,6 +109,7 @@
|
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
- (void)destroy {
|
|
112
|
+
[self dismissNonBubbledCallout];
|
|
106
113
|
[self stopEdgeInsetsAnimation];
|
|
107
114
|
if (_tapGesture) {
|
|
108
115
|
[_mapView removeGestureRecognizer:_tapGesture];
|
|
@@ -319,11 +326,24 @@
|
|
|
319
326
|
return NO;
|
|
320
327
|
}
|
|
321
328
|
|
|
329
|
+
- (BOOL)hitTestCalloutAtPoint:(CGPoint)point {
|
|
330
|
+
if (!_activeNonBubbledMarker)
|
|
331
|
+
return NO;
|
|
332
|
+
|
|
333
|
+
UIView *contentView = _activeNonBubbledMarker.calloutView.contentView;
|
|
334
|
+
CGPoint local = [contentView convertPoint:point fromView:_mapView];
|
|
335
|
+
return [contentView pointInside:local withEvent:nil];
|
|
336
|
+
}
|
|
337
|
+
|
|
322
338
|
- (void)handleTap:(UITapGestureRecognizer *)gesture {
|
|
323
339
|
if (gesture.state != UIGestureRecognizerStateEnded)
|
|
324
340
|
return;
|
|
325
341
|
|
|
326
342
|
CGPoint point = [gesture locationInView:_mapView];
|
|
343
|
+
if ([self hitTestCalloutAtPoint:point])
|
|
344
|
+
return;
|
|
345
|
+
|
|
346
|
+
[self dismissNonBubbledCallout];
|
|
327
347
|
|
|
328
348
|
if ([self hitTestAnnotationAtPoint:point])
|
|
329
349
|
return;
|
|
@@ -390,6 +410,7 @@
|
|
|
390
410
|
longitude:mapView.centerCoordinate.longitude
|
|
391
411
|
zoom:mapView.zoomLevel
|
|
392
412
|
gesture:_isDragging];
|
|
413
|
+
[self positionNonBubbledCallout];
|
|
393
414
|
}
|
|
394
415
|
|
|
395
416
|
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
|
|
@@ -423,22 +444,23 @@
|
|
|
423
444
|
}
|
|
424
445
|
|
|
425
446
|
if (!markerView.hasCustomView) {
|
|
426
|
-
|
|
427
|
-
[[
|
|
428
|
-
|
|
447
|
+
LuggMarkerAnnotationView *markerAnnotationView =
|
|
448
|
+
[[LuggMarkerAnnotationView alloc] initWithAnnotation:annotation
|
|
449
|
+
reuseIdentifier:nil];
|
|
429
450
|
markerAnnotationView.canShowCallout = YES;
|
|
430
451
|
markerAnnotationView.displayPriority = MKFeatureDisplayPriorityRequired;
|
|
431
452
|
markerAnnotationView.layer.zPosition = markerView.zIndex;
|
|
432
453
|
markerAnnotationView.zPriority = markerView.zIndex;
|
|
433
454
|
markerAnnotationView.draggable = markerView.draggable;
|
|
455
|
+
[self applyCalloutView:markerView annotationView:markerAnnotationView];
|
|
434
456
|
[self addCenterTapGesture:markerAnnotationView];
|
|
435
457
|
markerAnnotation.annotationView = markerAnnotationView;
|
|
436
458
|
return markerAnnotationView;
|
|
437
459
|
}
|
|
438
460
|
|
|
439
|
-
|
|
440
|
-
[[
|
|
441
|
-
|
|
461
|
+
LuggAnnotationView *annotationView =
|
|
462
|
+
[[LuggAnnotationView alloc] initWithAnnotation:annotation
|
|
463
|
+
reuseIdentifier:nil];
|
|
442
464
|
annotationView.canShowCallout = YES;
|
|
443
465
|
annotationView.displayPriority = MKFeatureDisplayPriorityRequired;
|
|
444
466
|
annotationView.layer.zPosition = markerView.zIndex;
|
|
@@ -446,6 +468,8 @@
|
|
|
446
468
|
annotationView.draggable = markerView.draggable;
|
|
447
469
|
[self addCenterTapGesture:annotationView];
|
|
448
470
|
|
|
471
|
+
[self applyCalloutView:markerView annotationView:annotationView];
|
|
472
|
+
|
|
449
473
|
if (!markerView.rasterize) {
|
|
450
474
|
UIView *iconView = markerView.iconView;
|
|
451
475
|
[iconView removeFromSuperview];
|
|
@@ -516,6 +540,104 @@
|
|
|
516
540
|
CGPoint point = [_mapView convertCoordinate:markerView.coordinate
|
|
517
541
|
toPointToView:_mapView];
|
|
518
542
|
[markerView emitPressEventWithPoint:point];
|
|
543
|
+
|
|
544
|
+
LuggCalloutView *calloutView = markerView.calloutView;
|
|
545
|
+
if (calloutView && !calloutView.bubbled && calloutView.hasCustomContent) {
|
|
546
|
+
[self showNonBubbledCallout:markerView];
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
- (void)mapView:(MKMapView *)mapView
|
|
552
|
+
didDeselectAnnotationView:(MKAnnotationView *)view {
|
|
553
|
+
if (![view.annotation isKindOfClass:[AppleMarkerAnnotation class]])
|
|
554
|
+
return;
|
|
555
|
+
|
|
556
|
+
AppleMarkerAnnotation *annotation = (AppleMarkerAnnotation *)view.annotation;
|
|
557
|
+
LuggMarkerView *markerView = annotation.markerView;
|
|
558
|
+
|
|
559
|
+
if (markerView && _activeNonBubbledMarker == markerView &&
|
|
560
|
+
!_isReselectingAnnotation) {
|
|
561
|
+
_isReselectingAnnotation = YES;
|
|
562
|
+
[_mapView selectAnnotation:annotation animated:NO];
|
|
563
|
+
_isReselectingAnnotation = NO;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
- (void)showNonBubbledCallout:(LuggMarkerView *)markerView {
|
|
568
|
+
[self dismissNonBubbledCallout];
|
|
569
|
+
|
|
570
|
+
LuggCalloutView *calloutView = markerView.calloutView;
|
|
571
|
+
UIView *contentView = calloutView.contentView;
|
|
572
|
+
[contentView removeFromSuperview];
|
|
573
|
+
|
|
574
|
+
contentView.userInteractionEnabled = YES;
|
|
575
|
+
calloutView.delegate = self;
|
|
576
|
+
|
|
577
|
+
AppleMarkerAnnotation *annotation =
|
|
578
|
+
(AppleMarkerAnnotation *)markerView.marker;
|
|
579
|
+
MKAnnotationView *annotationView = annotation.annotationView;
|
|
580
|
+
if (annotationView) {
|
|
581
|
+
annotationView.clipsToBounds = NO;
|
|
582
|
+
[annotationView addSubview:contentView];
|
|
583
|
+
} else {
|
|
584
|
+
[_wrapperView addSubview:contentView];
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
_activeNonBubbledMarker = markerView;
|
|
588
|
+
[self positionNonBubbledCallout];
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
- (void)calloutViewDidUpdate:(LuggCalloutView *)calloutView {
|
|
592
|
+
[self positionNonBubbledCallout];
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
- (void)positionNonBubbledCallout {
|
|
596
|
+
if (!_activeNonBubbledMarker)
|
|
597
|
+
return;
|
|
598
|
+
|
|
599
|
+
LuggCalloutView *calloutView = _activeNonBubbledMarker.calloutView;
|
|
600
|
+
UIView *contentView = calloutView.contentView;
|
|
601
|
+
CGSize contentSize = contentView.bounds.size;
|
|
602
|
+
if (contentSize.width <= 0 || contentSize.height <= 0)
|
|
603
|
+
return;
|
|
604
|
+
|
|
605
|
+
CGPoint anchor = calloutView.anchor;
|
|
606
|
+
|
|
607
|
+
AppleMarkerAnnotation *annotation =
|
|
608
|
+
(AppleMarkerAnnotation *)_activeNonBubbledMarker.marker;
|
|
609
|
+
MKAnnotationView *annotationView = annotation.annotationView;
|
|
610
|
+
|
|
611
|
+
if (annotationView && contentView.superview == annotationView) {
|
|
612
|
+
CGPoint center = CGPointMake(annotationView.bounds.size.width / 2.0 +
|
|
613
|
+
contentSize.width * (0.5 - anchor.x),
|
|
614
|
+
annotationView.bounds.size.height / 2.0 +
|
|
615
|
+
contentSize.height * (0.5 - anchor.y));
|
|
616
|
+
contentView.center = center;
|
|
617
|
+
} else {
|
|
618
|
+
CGPoint point =
|
|
619
|
+
[_mapView convertCoordinate:_activeNonBubbledMarker.coordinate
|
|
620
|
+
toPointToView:_wrapperView];
|
|
621
|
+
contentView.center =
|
|
622
|
+
CGPointMake(point.x + contentSize.width * (0.5 - anchor.x),
|
|
623
|
+
point.y + contentSize.height * (0.5 - anchor.y));
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
- (void)dismissNonBubbledCallout {
|
|
628
|
+
if (!_activeNonBubbledMarker)
|
|
629
|
+
return;
|
|
630
|
+
|
|
631
|
+
LuggMarkerView *markerView = _activeNonBubbledMarker;
|
|
632
|
+
_activeNonBubbledMarker = nil;
|
|
633
|
+
|
|
634
|
+
markerView.calloutView.delegate = nil;
|
|
635
|
+
[markerView.calloutView.contentView removeFromSuperview];
|
|
636
|
+
|
|
637
|
+
AppleMarkerAnnotation *annotation =
|
|
638
|
+
(AppleMarkerAnnotation *)markerView.marker;
|
|
639
|
+
if (annotation) {
|
|
640
|
+
[_mapView deselectAnnotation:annotation animated:NO];
|
|
519
641
|
}
|
|
520
642
|
}
|
|
521
643
|
|
|
@@ -574,6 +696,27 @@
|
|
|
574
696
|
}
|
|
575
697
|
}
|
|
576
698
|
|
|
699
|
+
- (void)applyCalloutView:(LuggMarkerView *)markerView
|
|
700
|
+
annotationView:(MKAnnotationView *)annotationView {
|
|
701
|
+
LuggCalloutView *calloutView = markerView.calloutView;
|
|
702
|
+
if (!calloutView) {
|
|
703
|
+
annotationView.detailCalloutAccessoryView = nil;
|
|
704
|
+
annotationView.rightCalloutAccessoryView = nil;
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
annotationView.rightCalloutAccessoryView = nil;
|
|
709
|
+
|
|
710
|
+
if (!calloutView.bubbled) {
|
|
711
|
+
annotationView.canShowCallout = NO;
|
|
712
|
+
annotationView.detailCalloutAccessoryView = nil;
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
annotationView.detailCalloutAccessoryView =
|
|
717
|
+
calloutView.hasCustomContent ? calloutView.contentView : nil;
|
|
718
|
+
}
|
|
719
|
+
|
|
577
720
|
#pragma mark - MarkerViewDelegate
|
|
578
721
|
|
|
579
722
|
- (void)markerViewDidLayout:(LuggMarkerView *)markerView {
|
|
@@ -600,6 +743,7 @@
|
|
|
600
743
|
annotationView.draggable = markerView.draggable;
|
|
601
744
|
annotationView.layer.zPosition = markerView.zIndex;
|
|
602
745
|
annotationView.zPriority = markerView.zIndex;
|
|
746
|
+
[self applyCalloutView:markerView annotationView:annotationView];
|
|
603
747
|
}
|
|
604
748
|
|
|
605
749
|
[self updateAnnotationViewFrame:annotation];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import "GoogleMapProvider.h"
|
|
2
|
+
#import "../LuggCalloutView.h"
|
|
2
3
|
#import "../LuggMarkerView.h"
|
|
3
4
|
#import "../LuggPolygonView.h"
|
|
4
5
|
#import "../LuggPolylineView.h"
|
|
@@ -8,10 +9,12 @@
|
|
|
8
9
|
static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
9
10
|
|
|
10
11
|
@interface GoogleMapProvider () <
|
|
11
|
-
LuggMarkerViewDelegate, LuggPolylineViewDelegate,
|
|
12
|
+
LuggMarkerViewDelegate, LuggCalloutViewDelegate, LuggPolylineViewDelegate,
|
|
13
|
+
LuggPolygonViewDelegate>
|
|
12
14
|
@end
|
|
13
15
|
|
|
14
16
|
@implementation GoogleMapProvider {
|
|
17
|
+
UIView *_wrapperView;
|
|
15
18
|
GMSMapView *_mapView;
|
|
16
19
|
BOOL _isMapReady;
|
|
17
20
|
BOOL _isDragging;
|
|
@@ -23,6 +26,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
23
26
|
NSMapTable<LuggPolylineView *, GMSPolylineAnimator *> *_polylineAnimators;
|
|
24
27
|
NSMapTable<GMSPolygon *, LuggPolygonView *> *_polygonToViewMap;
|
|
25
28
|
NSMapTable<GMSMarker *, LuggMarkerView *> *_markerToViewMap;
|
|
29
|
+
LuggMarkerView *_activeNonBubbledMarker;
|
|
26
30
|
|
|
27
31
|
// Edge insets animation
|
|
28
32
|
CADisplayLink *_edgeInsetsDisplayLink;
|
|
@@ -88,6 +92,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
88
92
|
_mapView.paddingAdjustmentBehavior =
|
|
89
93
|
kGMSMapViewPaddingAdjustmentBehaviorNever;
|
|
90
94
|
|
|
95
|
+
_wrapperView = wrapperView;
|
|
91
96
|
[wrapperView addSubview:_mapView];
|
|
92
97
|
|
|
93
98
|
[self applyTheme];
|
|
@@ -248,6 +253,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
248
253
|
longitude:position.target.longitude
|
|
249
254
|
zoom:position.zoom
|
|
250
255
|
gesture:_isDragging];
|
|
256
|
+
[self positionNonBubbledCallout];
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
- (void)mapView:(GMSMapView *)mapView
|
|
@@ -267,6 +273,7 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
267
273
|
|
|
268
274
|
- (void)mapView:(GMSMapView *)mapView
|
|
269
275
|
didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
|
|
276
|
+
[self dismissNonBubbledCallout];
|
|
270
277
|
CGPoint point = [mapView.projection pointForCoordinate:coordinate];
|
|
271
278
|
[_delegate mapProviderDidPress:coordinate.latitude
|
|
272
279
|
longitude:coordinate.longitude
|
|
@@ -296,10 +303,19 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
296
303
|
}
|
|
297
304
|
|
|
298
305
|
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
|
|
306
|
+
[self dismissNonBubbledCallout];
|
|
307
|
+
|
|
299
308
|
LuggMarkerView *markerView = [_markerToViewMap objectForKey:marker];
|
|
300
309
|
if (markerView) {
|
|
301
310
|
CGPoint point = [_mapView.projection pointForCoordinate:marker.position];
|
|
302
311
|
[markerView emitPressEventWithPoint:point];
|
|
312
|
+
|
|
313
|
+
LuggCalloutView *calloutView = markerView.calloutView;
|
|
314
|
+
if (calloutView && !calloutView.bubbled && calloutView.hasCustomContent) {
|
|
315
|
+
[mapView animateToLocation:marker.position];
|
|
316
|
+
[self showNonBubbledCallout:markerView];
|
|
317
|
+
return YES;
|
|
318
|
+
}
|
|
303
319
|
}
|
|
304
320
|
return NO;
|
|
305
321
|
}
|
|
@@ -332,6 +348,95 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
332
348
|
}
|
|
333
349
|
}
|
|
334
350
|
|
|
351
|
+
- (UIView *)rasterizedCalloutView:(LuggCalloutView *)calloutView {
|
|
352
|
+
UIView *contentView = calloutView.contentView;
|
|
353
|
+
[contentView layoutIfNeeded];
|
|
354
|
+
|
|
355
|
+
CGSize size = contentView.bounds.size;
|
|
356
|
+
if (size.width <= 0 || size.height <= 0)
|
|
357
|
+
return nil;
|
|
358
|
+
|
|
359
|
+
UIGraphicsImageRendererFormat *format =
|
|
360
|
+
[UIGraphicsImageRendererFormat defaultFormat];
|
|
361
|
+
format.scale = [UIScreen mainScreen].scale;
|
|
362
|
+
UIGraphicsImageRenderer *renderer =
|
|
363
|
+
[[UIGraphicsImageRenderer alloc] initWithSize:size format:format];
|
|
364
|
+
UIImage *image =
|
|
365
|
+
[renderer imageWithActions:^(UIGraphicsImageRendererContext *context) {
|
|
366
|
+
[contentView.layer renderInContext:context.CGContext];
|
|
367
|
+
}];
|
|
368
|
+
|
|
369
|
+
return [[UIImageView alloc] initWithImage:image];
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
|
|
373
|
+
// Non-bubbled callouts are rendered as live views, not info windows
|
|
374
|
+
return nil;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
- (UIView *)mapView:(GMSMapView *)mapView
|
|
378
|
+
markerInfoContents:(GMSMarker *)marker {
|
|
379
|
+
LuggMarkerView *markerView = [_markerToViewMap objectForKey:marker];
|
|
380
|
+
if (!markerView || !markerView.calloutView ||
|
|
381
|
+
!markerView.calloutView.hasCustomContent)
|
|
382
|
+
return nil;
|
|
383
|
+
|
|
384
|
+
if (markerView.calloutView.bubbled) {
|
|
385
|
+
return [self rasterizedCalloutView:markerView.calloutView];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
return nil;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
- (void)showNonBubbledCallout:(LuggMarkerView *)markerView {
|
|
392
|
+
[self dismissNonBubbledCallout];
|
|
393
|
+
_mapView.selectedMarker = nil;
|
|
394
|
+
|
|
395
|
+
LuggCalloutView *calloutView = markerView.calloutView;
|
|
396
|
+
UIView *contentView = calloutView.contentView;
|
|
397
|
+
[contentView removeFromSuperview];
|
|
398
|
+
|
|
399
|
+
contentView.userInteractionEnabled = YES;
|
|
400
|
+
calloutView.delegate = self;
|
|
401
|
+
[_wrapperView addSubview:contentView];
|
|
402
|
+
|
|
403
|
+
_activeNonBubbledMarker = markerView;
|
|
404
|
+
[self positionNonBubbledCallout];
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
- (void)calloutViewDidUpdate:(LuggCalloutView *)calloutView {
|
|
408
|
+
[self positionNonBubbledCallout];
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
- (void)dismissNonBubbledCallout {
|
|
412
|
+
if (!_activeNonBubbledMarker)
|
|
413
|
+
return;
|
|
414
|
+
|
|
415
|
+
LuggCalloutView *calloutView = _activeNonBubbledMarker.calloutView;
|
|
416
|
+
calloutView.delegate = nil;
|
|
417
|
+
[calloutView.contentView removeFromSuperview];
|
|
418
|
+
_activeNonBubbledMarker = nil;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
- (void)positionNonBubbledCallout {
|
|
422
|
+
if (!_activeNonBubbledMarker)
|
|
423
|
+
return;
|
|
424
|
+
|
|
425
|
+
LuggCalloutView *calloutView = _activeNonBubbledMarker.calloutView;
|
|
426
|
+
UIView *contentView = calloutView.contentView;
|
|
427
|
+
CGSize contentSize = contentView.bounds.size;
|
|
428
|
+
if (contentSize.width <= 0 || contentSize.height <= 0)
|
|
429
|
+
return;
|
|
430
|
+
|
|
431
|
+
CGPoint anchor = calloutView.anchor;
|
|
432
|
+
CGPoint point = [_mapView.projection
|
|
433
|
+
pointForCoordinate:_activeNonBubbledMarker.coordinate];
|
|
434
|
+
|
|
435
|
+
contentView.center =
|
|
436
|
+
CGPointMake(point.x + contentSize.width * (0.5 - anchor.x),
|
|
437
|
+
point.y + contentSize.height * (0.5 - anchor.y));
|
|
438
|
+
}
|
|
439
|
+
|
|
335
440
|
#pragma mark - MarkerViewDelegate
|
|
336
441
|
|
|
337
442
|
- (void)markerViewDidLayout:(LuggMarkerView *)markerView {
|
|
@@ -387,8 +492,10 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
387
492
|
|
|
388
493
|
GMSAdvancedMarker *marker = (GMSAdvancedMarker *)markerView.marker;
|
|
389
494
|
marker.position = markerView.coordinate;
|
|
390
|
-
marker.title = markerView.title;
|
|
391
|
-
marker.snippet = markerView.markerDescription
|
|
495
|
+
marker.title = markerView.title.length > 0 ? markerView.title : nil;
|
|
496
|
+
marker.snippet = markerView.markerDescription.length > 0
|
|
497
|
+
? markerView.markerDescription
|
|
498
|
+
: nil;
|
|
392
499
|
marker.zIndex = (int)markerView.zIndex;
|
|
393
500
|
marker.draggable = markerView.draggable;
|
|
394
501
|
[self applyMarkerStyle:markerView marker:marker];
|
|
@@ -410,8 +517,10 @@ static NSString *const kDemoMapId = @"DEMO_MAP_ID";
|
|
|
410
517
|
|
|
411
518
|
GMSAdvancedMarker *marker = [[GMSAdvancedMarker alloc] init];
|
|
412
519
|
marker.position = markerView.coordinate;
|
|
413
|
-
marker.title = markerView.title;
|
|
414
|
-
marker.snippet = markerView.markerDescription
|
|
520
|
+
marker.title = markerView.title.length > 0 ? markerView.title : nil;
|
|
521
|
+
marker.snippet = markerView.markerDescription.length > 0
|
|
522
|
+
? markerView.markerDescription
|
|
523
|
+
: nil;
|
|
415
524
|
marker.zIndex = (int)markerView.zIndex;
|
|
416
525
|
marker.draggable = markerView.draggable;
|
|
417
526
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#import <MapKit/MapKit.h>
|
|
2
|
+
|
|
3
|
+
@interface LuggAnnotationView : MKAnnotationView
|
|
4
|
+
@end
|
|
5
|
+
|
|
6
|
+
@interface LuggMarkerAnnotationView : MKMarkerAnnotationView
|
|
7
|
+
@end
|
|
8
|
+
|
|
9
|
+
// Shared hit-test helpers for annotation views with subviews outside bounds
|
|
10
|
+
BOOL LuggAnnotationPointInside(UIView *self, CGPoint point, UIEvent *event);
|
|
11
|
+
UIView *_Nullable LuggAnnotationHitTest(UIView *self, CGPoint point,
|
|
12
|
+
UIEvent *event);
|