[ios] Optional positioning and stickiness for callout view
This commit is contained in:
committed by
Minh Nguyễn
parent
57644b2804
commit
f1fc9bdfeb
@@ -7,4 +7,8 @@
|
||||
* callout title for demonstration purpose.
|
||||
*/
|
||||
@interface MBXCustomCalloutView : UIView <MGLCalloutView>
|
||||
|
||||
@property (nonatomic, assign, getter=isAnchoredToAnnotation) BOOL anchoredToAnnotation;
|
||||
@property (nonatomic, assign) BOOL dismissesAutomatically;
|
||||
|
||||
@end
|
||||
|
||||
@@ -17,6 +17,8 @@ static CGFloat const tipWidth = 10.0;
|
||||
}
|
||||
|
||||
@synthesize representedObject = _representedObject;
|
||||
@synthesize anchoredToAnnotation = _anchoredToAnnotation;
|
||||
@synthesize dismissesAutomatically = _dismissesAutomatically;
|
||||
@synthesize leftAccessoryView = _leftAccessoryView;
|
||||
@synthesize rightAccessoryView = _rightAccessoryView;
|
||||
@synthesize delegate = _delegate;
|
||||
@@ -66,6 +68,11 @@ static CGFloat const tipWidth = 10.0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setCenter:(CGPoint)center {
|
||||
center.y = center.y - CGRectGetMidY(self.bounds);
|
||||
[super setCenter:center];
|
||||
}
|
||||
|
||||
- (void)dismissCalloutAnimated:(BOOL)animated
|
||||
{
|
||||
if (self.superview)
|
||||
|
||||
@@ -89,6 +89,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
|
||||
@end
|
||||
|
||||
@interface MBXCustomCalloutAnnotation : MGLPointAnnotation
|
||||
@property (nonatomic, assign) BOOL anchoredToAnnotation;
|
||||
@property (nonatomic, assign) BOOL dismissesAutomatically;
|
||||
@end
|
||||
|
||||
@implementation MBXCustomCalloutAnnotation
|
||||
@@ -699,12 +701,28 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
|
||||
{
|
||||
[self.mapView removeAnnotations:self.mapView.annotations];
|
||||
|
||||
MBXCustomCalloutAnnotation *annotation = [[MBXCustomCalloutAnnotation alloc] init];
|
||||
annotation.coordinate = CLLocationCoordinate2DMake(48.8533940, 2.3775439);
|
||||
annotation.title = @"Custom Callout";
|
||||
MBXCustomCalloutAnnotation *firstAnnotation = [[MBXCustomCalloutAnnotation alloc] init];
|
||||
firstAnnotation.coordinate = CLLocationCoordinate2DMake(48.8533940, 2.3775439);
|
||||
firstAnnotation.title = @"Open anchored to annotation";
|
||||
firstAnnotation.anchoredToAnnotation = YES;
|
||||
firstAnnotation.dismissesAutomatically = NO;
|
||||
|
||||
MBXCustomCalloutAnnotation *secondAnnotation = [[MBXCustomCalloutAnnotation alloc] init];
|
||||
secondAnnotation.coordinate = CLLocationCoordinate2DMake(48.8543940, 2.3775439);
|
||||
secondAnnotation.title = @"Open not anchored to annotation";
|
||||
secondAnnotation.anchoredToAnnotation = NO;
|
||||
secondAnnotation.dismissesAutomatically = NO;
|
||||
|
||||
[self.mapView addAnnotation:annotation];
|
||||
[self.mapView showAnnotations:@[annotation] animated:YES];
|
||||
MBXCustomCalloutAnnotation *thirdAnnotation = [[MBXCustomCalloutAnnotation alloc] init];
|
||||
thirdAnnotation.coordinate = CLLocationCoordinate2DMake(48.8553940, 2.3775439);
|
||||
thirdAnnotation.title = @"Dismisses automatically";
|
||||
thirdAnnotation.anchoredToAnnotation = YES;
|
||||
thirdAnnotation.dismissesAutomatically = YES;
|
||||
|
||||
NSArray *annotations = @[firstAnnotation, secondAnnotation, thirdAnnotation];
|
||||
[self.mapView addAnnotations:annotations];
|
||||
|
||||
[self.mapView showAnnotations:annotations animated:YES];
|
||||
}
|
||||
|
||||
- (void)styleWaterLayer
|
||||
@@ -1582,8 +1600,11 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
|
||||
if ([annotation respondsToSelector:@selector(title)]
|
||||
&& [annotation isKindOfClass:[MBXCustomCalloutAnnotation class]])
|
||||
{
|
||||
MBXCustomCalloutAnnotation *customAnnotation = (MBXCustomCalloutAnnotation *)annotation;
|
||||
MBXCustomCalloutView *calloutView = [[MBXCustomCalloutView alloc] init];
|
||||
calloutView.representedObject = annotation;
|
||||
calloutView.anchoredToAnnotation = customAnnotation.anchoredToAnnotation;
|
||||
calloutView.dismissesAutomatically = customAnnotation.dismissesAutomatically;
|
||||
return calloutView;
|
||||
}
|
||||
return nil;
|
||||
|
||||
@@ -46,6 +46,24 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)dismissCalloutAnimated:(BOOL)animated;
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
A Boolean value indicating whether the callout view should be anchored to
|
||||
the corresponding annotation. You can adjust the callout view’s precise location by
|
||||
overriding -[UIView setCenter:]. The callout view will not be anchored to the
|
||||
annotation if this optional property is unimplemented.
|
||||
*/
|
||||
@property (nonatomic, readonly, assign, getter=isAnchoredToAnnotation) BOOL anchoredToAnnotation;
|
||||
|
||||
/**
|
||||
A Boolean value indicating whether the callout view should be dismissed automatically
|
||||
when the map view’s viewport changes. Note that a single tap on the map view
|
||||
still dismisses the callout view regardless of the value of this property.
|
||||
The callout view will be dismissed if this optional property is unimplemented.
|
||||
*/
|
||||
@property (nonatomic, readonly, assign) BOOL dismissesAutomatically;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,14 @@
|
||||
return [[self alloc] init];
|
||||
}
|
||||
|
||||
- (BOOL)isAnchoredToAnnotation {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)dismissesAutomatically {
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setRepresentedObject:(id <MGLAnnotation>)representedObject
|
||||
{
|
||||
_representedObject = representedObject;
|
||||
|
||||
@@ -4561,21 +4561,34 @@ public:
|
||||
|| self.userTrackingMode == MGLUserTrackingModeNone
|
||||
|| self.userTrackingState != MGLUserTrackingStateChanged)
|
||||
{
|
||||
// Deselect annotation if it lies outside the viewport
|
||||
if (self.selectedAnnotation) {
|
||||
MGLAnnotationTag tag = [self annotationTagForAnnotation:self.selectedAnnotation];
|
||||
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag);
|
||||
MGLAnnotationView *annotationView = annotationContext.annotationView;
|
||||
|
||||
CGRect rect = [self positioningRectForCalloutForAnnotationWithTag:tag];
|
||||
|
||||
if (annotationView)
|
||||
{
|
||||
rect = annotationView.frame;
|
||||
}
|
||||
|
||||
if ( ! CGRectIntersectsRect(rect, self.frame)) {
|
||||
[self deselectAnnotation:self.selectedAnnotation animated:NO];
|
||||
UIView<MGLCalloutView> *calloutView = self.calloutViewForSelectedAnnotation;
|
||||
BOOL dismissesAutomatically = (calloutView
|
||||
&& [calloutView respondsToSelector:@selector(dismissesAutomatically)]
|
||||
&& calloutView.dismissesAutomatically);
|
||||
// dismissesAutomatically is an optional property and we want to dismiss
|
||||
// the callout view if it's unimplemented.
|
||||
if (dismissesAutomatically || ![calloutView respondsToSelector:@selector(dismissesAutomatically)])
|
||||
{
|
||||
[self deselectAnnotation:self.selectedAnnotation animated:NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deselect annotation if it lies outside the viewport
|
||||
if (self.selectedAnnotation) {
|
||||
MGLAnnotationTag tag = [self annotationTagForAnnotation:self.selectedAnnotation];
|
||||
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag);
|
||||
MGLAnnotationView *annotationView = annotationContext.annotationView;
|
||||
|
||||
CGRect rect = [self positioningRectForCalloutForAnnotationWithTag:tag];
|
||||
|
||||
if (annotationView)
|
||||
{
|
||||
rect = annotationView.frame;
|
||||
}
|
||||
|
||||
if ( ! CGRectIntersectsRect(rect, self.frame)) {
|
||||
[self deselectAnnotation:self.selectedAnnotation animated:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4816,7 +4829,12 @@ public:
|
||||
UIView <MGLCalloutView> *calloutView = self.calloutViewForSelectedAnnotation;
|
||||
id <MGLAnnotation> annotation = calloutView.representedObject;
|
||||
|
||||
if (calloutView && annotation)
|
||||
BOOL isAnchoredToAnnotation = (calloutView
|
||||
&& annotation
|
||||
&& [calloutView respondsToSelector:@selector(isAnchoredToAnnotation)]
|
||||
&& calloutView.isAnchoredToAnnotation);
|
||||
|
||||
if (isAnchoredToAnnotation)
|
||||
{
|
||||
MGLAnnotationTag tag = [self annotationTagForAnnotation:annotation];
|
||||
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(tag);
|
||||
|
||||
Reference in New Issue
Block a user