summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorJesse Bounds <jesse@rebounds.net>2016-06-23 12:04:23 -0700
committerJesse Bounds <jesse@rebounds.net>2016-06-23 12:04:23 -0700
commit05b6e724935277920a2c5f8282993b50d26f9719 (patch)
tree20e7b108832ee3c47d9f1949a21d1f9327a3d9a6 /platform
parentf5f39c8b3adfed4c4c102dca5d5be4d6cfc0b69f (diff)
downloadqtlocation-mapboxgl-05b6e724935277920a2c5f8282993b50d26f9719.tar.gz
[ios] Cycle through both UIView and UIImage backed annotations
This changes the way the the calculation for the largest visual annotation representation (stored in _unionedAnnotationRepresentationSize) is done so that it includes both images and views. The `annotationTagAtPoint` method is then able to find annotation objects that are in a query rect formed from the sizes of all manner of point annotation visual representations. The `annotationTagAtPoint` method also gains new logic in a conditional to handle annotations backed by MGLAnnotationViews. Similarly to the image case, it filters out disabled annotations and calculates a centered rect for the view. The hit test logic remains the same but now works correctly for both the centered rects of both images and views. This also fixes a bug where the `largestAnnotationViewSize` was always holding the last annotation view size and not necessarily the largest. This would affect when annotation views are put into a reuse queue since the size is used to help determine when an annotation view has gone offscreen.
Diffstat (limited to 'platform')
-rw-r--r--platform/ios/src/MGLMapView.mm69
1 files changed, 42 insertions, 27 deletions
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 2c76f3b850..5c6c322f64 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -255,8 +255,9 @@ public:
NS_MUTABLE_DICTIONARY_OF(NSString *, NS_MUTABLE_ARRAY_OF(MGLAnnotationView *) *) *_annotationViewReuseQueueByIdentifier;
BOOL _userLocationAnnotationIsSelected;
- /// Size of the rectangle formed by unioning the maximum slop area around every annotation image.
- CGSize _unionedAnnotationImageSize;
+ /// Size of the rectangle formed by unioning the maximum slop area around every annotation image and annotation image view.
+ CGSize _unionedAnnotationRepresentationSize;
+ CGSize _largestAnnotationViewSize;
std::vector<MGLAnnotationTag> _annotationsNearbyLastTap;
CGPoint _initialImplicitCalloutViewOffset;
NSDate *_userLocationAnimationCompletionDate;
@@ -282,8 +283,6 @@ public:
BOOL _delegateHasLineWidthsForShapeAnnotations;
MGLCompassDirectionFormatter *_accessibilityCompassFormatter;
-
- CGSize _largestAnnotationViewSize;
}
#pragma mark - Setup & Teardown -
@@ -1413,13 +1412,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
}
return;
}
-
- MGLAnnotationView *hitAnnotationView = [self annotationViewAtPoint:tapPoint];
- if (hitAnnotationView)
- {
- [self selectAnnotation:hitAnnotationView.annotation animated:YES];
- return;
- }
MGLAnnotationTag hitAnnotationTag = [self annotationTagAtPoint:tapPoint persistingResults:YES];
if (hitAnnotationTag != MGLAnnotationTagNotFound)
@@ -2978,7 +2970,12 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
{
annotationView.annotation = annotation;
CGRect bounds = UIEdgeInsetsInsetRect({ CGPointZero, annotationView.frame.size }, annotationView.alignmentRectInsets);
- _largestAnnotationViewSize = CGSizeMake(bounds.size.width / 2.0, bounds.size.height / 2.0);
+
+ _largestAnnotationViewSize = CGSizeMake(MAX(_largestAnnotationViewSize.width, CGRectGetWidth(bounds)),
+ MAX(_largestAnnotationViewSize.height, CGRectGetHeight(bounds)));
+
+ _unionedAnnotationRepresentationSize = CGSizeMake(MAX(_unionedAnnotationRepresentationSize.width, _largestAnnotationViewSize.width),
+ MAX(_unionedAnnotationRepresentationSize.height, _largestAnnotationViewSize.height));
}
return annotationView;
@@ -3060,8 +3057,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
// within this image. Union this slop area with any existing slop areas.
CGRect bounds = UIEdgeInsetsInsetRect({ CGPointZero, annotationImage.image.size },
annotationImage.image.alignmentRectInsets);
- _unionedAnnotationImageSize = CGSizeMake(MAX(_unionedAnnotationImageSize.width, bounds.size.width),
- MAX(_unionedAnnotationImageSize.height, bounds.size.height));
+ _unionedAnnotationRepresentationSize = CGSizeMake(MAX(_unionedAnnotationRepresentationSize.width, bounds.size.width),
+ MAX(_unionedAnnotationRepresentationSize.height, bounds.size.height));
}
- (void)removeAnnotation:(id <MGLAnnotation>)annotation
@@ -3199,10 +3196,10 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
{
// Look for any annotation near the tap. An annotation is “near” if the
// distance between its center and the tap is less than the maximum height
- // or width of an installed annotation image.
+ // or width of an installed annotation image or annotation view.
CGRect queryRect = CGRectInset({ point, CGSizeZero },
- -_unionedAnnotationImageSize.width,
- -_unionedAnnotationImageSize.height);
+ -_unionedAnnotationRepresentationSize.width,
+ -_unionedAnnotationRepresentationSize.height);
queryRect = CGRectInset(queryRect, -MGLAnnotationImagePaddingForHitTest,
-MGLAnnotationImagePaddingForHitTest);
std::vector<MGLAnnotationTag> nearbyAnnotations = [self annotationTagsInRect:queryRect];
@@ -3214,10 +3211,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
-MGLAnnotationImagePaddingForHitTest,
-MGLAnnotationImagePaddingForHitTest);
- MGLAnnotationImage *fallbackAnnotationImage = [self dequeueReusableAnnotationImageWithIdentifier:MGLDefaultStyleMarkerSymbolName];
- UIImage *fallbackImage = fallbackAnnotationImage.image;
-
- // Filter out any annotation whose image is unselectable or for which
+ // Filter out any annotation whose image or view is unselectable or for which
// hit testing fails.
auto end = std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(),
[&](const MGLAnnotationTag annotationTag)
@@ -3226,17 +3220,36 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
NSAssert(annotation, @"Unknown annotation found nearby tap");
MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag[annotationTag];
+ CGRect annotationRect;
- MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
- if ( ! annotationImage.enabled)
+ MGLAnnotationView *annotationView = annotationContext.annotationView;
+ if (annotationView)
{
- return true;
+ if ( ! annotationView.enabled)
+ {
+ return true;
+ }
+
+ CGPoint calloutAnchorPoint = [self convertCoordinate:annotation.coordinate toPointToView:self];
+ CGRect frame = CGRectInset({ calloutAnchorPoint, CGSizeZero }, -CGRectGetWidth(annotationView.frame) / 2, -CGRectGetHeight(annotationView.frame) / 2);
+ annotationRect = UIEdgeInsetsInsetRect(frame, annotationView.alignmentRectInsets);
+ }
+ else
+ {
+ MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
+ if ( ! annotationImage.enabled)
+ {
+ return true;
+ }
+
+ MGLAnnotationImage *fallbackAnnotationImage = [self dequeueReusableAnnotationImageWithIdentifier:MGLDefaultStyleMarkerSymbolName];
+ UIImage *fallbackImage = fallbackAnnotationImage.image;
+
+ annotationRect = [self frameOfImage:annotationImage.image ?: fallbackImage centeredAtCoordinate:annotation.coordinate];
}
// Filter out the annotation if the fattened finger didn’t land
// within the image’s alignment rect.
- CGRect annotationRect = [self frameOfImage:annotationImage.image ?: fallbackImage centeredAtCoordinate:annotation.coordinate];
-
return !!!CGRectIntersectsRect(annotationRect, hitRect);
});
@@ -4509,7 +4522,9 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
for (auto &pair : _annotationContextsByAnnotationTag)
{
- CGRect viewPort = CGRectInset(self.bounds, -_largestAnnotationViewSize.width - MGLAnnotationUpdateViewportOutset.width, -_largestAnnotationViewSize.height - MGLAnnotationUpdateViewportOutset.width);
+ CGRect viewPort = CGRectInset(self.bounds,
+ -_largestAnnotationViewSize.width / 2.0 - MGLAnnotationUpdateViewportOutset.width / 2.0,
+ -_largestAnnotationViewSize.height / 2.0 - MGLAnnotationUpdateViewportOutset.width);
MGLAnnotationContext &annotationContext = pair.second;
MGLAnnotationView *annotationView = annotationContext.annotationView;