[ios, macos] Center shape annotation's callout when offscreen. (#10255)
* [ios, macos] Center annotation's anchor to tap point when coordinate center is offscreen. * [ios, macos] Update changelogs.
This commit is contained in:
committed by
GitHub
parent
03d3aee6fc
commit
63f7963a93
@@ -32,6 +32,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
|
||||
* Added `-[MGLMapView cameraThatFitsShape:direction:edgePadding:]` to get a camera with zoom level and center coordinate computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107))
|
||||
* Added support selection of shape and polyline annotations.([#9984](https://github.com/mapbox/mapbox-gl-native/pull/9984))
|
||||
* Fixed an issue where view annotations could be slightly misaligned. View annotation placement is now rounded to the nearest pixel. ([#10219](https://github.com/mapbox/mapbox-gl-native/pull/10219))
|
||||
* Fixed an issue where a shape annotation callout was not displayed if the centroid was not visible. ([#10255](https://github.com/mapbox/mapbox-gl-native/pull/10255))
|
||||
|
||||
### Other changes
|
||||
|
||||
|
||||
@@ -1615,7 +1615,9 @@ public:
|
||||
id<MGLAnnotation>annotation = [self annotationForGestureRecognizer:singleTap persistingResults:YES];
|
||||
if(annotation)
|
||||
{
|
||||
[self selectAnnotation:annotation animated:YES];
|
||||
CGPoint calloutPoint = [singleTap locationInView:self];
|
||||
CGRect positionRect = [self positioningRectForAnnotation:annotation defaultCalloutPoint:calloutPoint];
|
||||
[self selectAnnotation:annotation animated:YES calloutPositioningRect:positionRect];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3979,6 +3981,12 @@ public:
|
||||
}
|
||||
|
||||
- (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated
|
||||
{
|
||||
CGRect positioningRect = [self positioningRectForAnnotation:annotation defaultCalloutPoint:CGPointZero];
|
||||
[self selectAnnotation:annotation animated:animated calloutPositioningRect:positioningRect];
|
||||
}
|
||||
|
||||
- (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated calloutPositioningRect:(CGRect)calloutPositioningRect
|
||||
{
|
||||
if ( ! annotation) return;
|
||||
|
||||
@@ -3995,9 +4003,6 @@ public:
|
||||
if (annotationTag == MGLAnnotationTagNotFound) return;
|
||||
}
|
||||
|
||||
// By default attempt to use the GL annotation image frame as the positioning rect.
|
||||
CGRect positioningRect = [self positioningRectForCalloutForAnnotationWithTag:annotationTag];
|
||||
|
||||
MGLAnnotationView *annotationView = nil;
|
||||
|
||||
if (annotation != self.userLocation)
|
||||
@@ -4005,21 +4010,12 @@ public:
|
||||
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
|
||||
annotationView = annotationContext.annotationView;
|
||||
if (annotationView && annotationView.enabled) {
|
||||
{
|
||||
// Annotations represented by views use the view frame as the positioning rect.
|
||||
positioningRect = annotationView.frame;
|
||||
[annotationView.superview bringSubviewToFront:annotationView];
|
||||
[annotationView setSelected:YES animated:animated];
|
||||
// Annotations represented by views use the view frame as the positioning rect.
|
||||
calloutPositioningRect = annotationView.frame;
|
||||
[annotationView.superview bringSubviewToFront:annotationView];
|
||||
[annotationView setSelected:YES animated:animated];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The client can request that any annotation be selected (even ones that are offscreen).
|
||||
// The annotation can’t be selected if no part of it is hittable.
|
||||
if ( ! CGRectIntersectsRect(positioningRect, self.bounds) && annotation != self.userLocation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.selectedAnnotation = annotation;
|
||||
|
||||
@@ -4049,7 +4045,7 @@ public:
|
||||
|
||||
if (_userLocationAnnotationIsSelected)
|
||||
{
|
||||
positioningRect = [self.userLocationAnnotationView.layer.presentationLayer frame];
|
||||
calloutPositioningRect = [self.userLocationAnnotationView.layer.presentationLayer frame];
|
||||
|
||||
CGRect implicitAnnotationFrame = [self.userLocationAnnotationView.layer.presentationLayer frame];
|
||||
CGRect explicitAnnotationFrame = self.userLocationAnnotationView.frame;
|
||||
@@ -4065,7 +4061,7 @@ public:
|
||||
if ([calloutView.leftAccessoryView isKindOfClass:[UIControl class]])
|
||||
{
|
||||
UITapGestureRecognizer *calloutAccessoryTap = [[UITapGestureRecognizer alloc] initWithTarget:self
|
||||
action:@selector(handleCalloutAccessoryTapGesture:)];
|
||||
action:@selector(handleCalloutAccessoryTapGesture:)];
|
||||
|
||||
[calloutView.leftAccessoryView addGestureRecognizer:calloutAccessoryTap];
|
||||
}
|
||||
@@ -4078,7 +4074,7 @@ public:
|
||||
if ([calloutView.rightAccessoryView isKindOfClass:[UIControl class]])
|
||||
{
|
||||
UITapGestureRecognizer *calloutAccessoryTap = [[UITapGestureRecognizer alloc] initWithTarget:self
|
||||
action:@selector(handleCalloutAccessoryTapGesture:)];
|
||||
action:@selector(handleCalloutAccessoryTapGesture:)];
|
||||
|
||||
[calloutView.rightAccessoryView addGestureRecognizer:calloutAccessoryTap];
|
||||
}
|
||||
@@ -4088,7 +4084,7 @@ public:
|
||||
calloutView.delegate = self;
|
||||
|
||||
// present popup
|
||||
[calloutView presentCalloutFromRect:positioningRect
|
||||
[calloutView presentCalloutFromRect:calloutPositioningRect
|
||||
inView:self.glView
|
||||
constrainedToView:self.glView
|
||||
animated:animated];
|
||||
@@ -4115,6 +4111,27 @@ public:
|
||||
return calloutView;
|
||||
}
|
||||
|
||||
/// Returns the rectangle that represents the annotation image of the annotation
|
||||
/// with the given tag. This rectangle is fitted to the image’s alignment rect
|
||||
/// and is appropriate for positioning a popover.
|
||||
/// If a shape annotation is visible but its centroid is not, and a default point is specified,
|
||||
/// the callout view is anchored to the default callout point.
|
||||
- (CGRect)positioningRectForAnnotation:(id <MGLAnnotation>)annotation defaultCalloutPoint:(CGPoint)calloutPoint
|
||||
{
|
||||
MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
|
||||
CGRect positioningRect = [self positioningRectForCalloutForAnnotationWithTag:annotationTag];
|
||||
|
||||
// For annotations which `coordinate` falls offscreen it will use the current tap point as anchor instead.
|
||||
if ( ! CGRectIntersectsRect(positioningRect, self.bounds) && annotation != self.userLocation)
|
||||
{
|
||||
if (!CGPointEqualToPoint(calloutPoint, CGPointZero)) {
|
||||
positioningRect = CGRectMake(calloutPoint.x, calloutPoint.y, positioningRect.size.width, positioningRect.size.height);
|
||||
}
|
||||
}
|
||||
|
||||
return positioningRect;
|
||||
}
|
||||
|
||||
/// Returns the rectangle that represents the annotation image of the annotation
|
||||
/// with the given tag. This rectangle is fitted to the image’s alignment rect
|
||||
/// and is appropriate for positioning a popover.
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
* Added an `overlays` property to `MGLMapView`. ([#8617](https://github.com/mapbox/mapbox-gl-native/pull/8617))
|
||||
* Added `-[MGLMapView cameraThatFitsShape:direction:edgePadding:]` to get a camera with zoom level and center coordinate computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107))
|
||||
* Added support selection of shape and polyline annotations.([#9984](https://github.com/mapbox/mapbox-gl-native/pull/9984))
|
||||
* Fixed an issue where a shape annotation callout was not displayed if the centroid was not visible. ([#10255](https://github.com/mapbox/mapbox-gl-native/pull/10255))
|
||||
|
||||
### Other changes
|
||||
|
||||
|
||||
@@ -1488,7 +1488,7 @@ public:
|
||||
if (hitAnnotationTag != _selectedAnnotationTag) {
|
||||
id <MGLAnnotation> annotation = [self annotationWithTag:hitAnnotationTag];
|
||||
NSAssert(annotation, @"Cannot select nonexistent annotation with tag %u", hitAnnotationTag);
|
||||
[self selectAnnotation:annotation];
|
||||
[self selectAnnotation:annotation atPoint:gesturePoint];
|
||||
}
|
||||
} else {
|
||||
[self deselectAnnotation:self.selectedAnnotation];
|
||||
@@ -2216,11 +2216,11 @@ public:
|
||||
|
||||
- (void)selectAnnotation:(id <MGLAnnotation>)annotation
|
||||
{
|
||||
// Only point annotations can be selected.
|
||||
if (!annotation || [annotation isKindOfClass:[MGLMultiPoint class]]) {
|
||||
return;
|
||||
}
|
||||
[self selectAnnotation:annotation atPoint:NSZeroPoint];
|
||||
}
|
||||
|
||||
- (void)selectAnnotation:(id <MGLAnnotation>)annotation atPoint:(NSPoint)gesturePoint
|
||||
{
|
||||
id <MGLAnnotation> selectedAnnotation = self.selectedAnnotation;
|
||||
if (annotation == selectedAnnotation) {
|
||||
return;
|
||||
@@ -2235,10 +2235,10 @@ public:
|
||||
[self addAnnotation:annotation];
|
||||
}
|
||||
|
||||
// The annotation can’t be selected if no part of it is hittable.
|
||||
// The annotation's anchor will bounce to the current click.
|
||||
NSRect positioningRect = [self positioningRectForCalloutForAnnotationWithTag:annotationTag];
|
||||
if (NSIsEmptyRect(NSIntersectionRect(positioningRect, self.bounds))) {
|
||||
return;
|
||||
positioningRect = CGRectMake(gesturePoint.x, gesturePoint.y, positioningRect.size.width, positioningRect.size.height);
|
||||
}
|
||||
|
||||
self.selectedAnnotation = annotation;
|
||||
|
||||
Reference in New Issue
Block a user