diff options
author | Julian Rex <julian.rex@gmail.com> | 2018-04-24 11:01:04 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-24 11:01:04 -0400 |
commit | 5b5549d644d026e093243b13e0770b9d34172ef9 (patch) | |
tree | 58aa4bc9cbc7cd78f00f4b2aed38570a21568717 /platform/ios | |
parent | fa6c6a3733323e855c1b825c9546093200cf0d62 (diff) | |
download | qtlocation-mapboxgl-5b5549d644d026e093243b13e0770b9d34172ef9.tar.gz |
[ios, macos] Fix for camera movement when selecting visible annotations (#11731)
Diffstat (limited to 'platform/ios')
-rw-r--r-- | platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme | 10 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 21 | ||||
-rw-r--r-- | platform/ios/test/MGLAnnotationViewTests.m | 89 |
3 files changed, 115 insertions, 5 deletions
diff --git a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme index 4679378126..afba168676 100644 --- a/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme +++ b/platform/ios/ios.xcodeproj/xcshareddata/xcschemes/CI.xcscheme @@ -54,7 +54,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> <Testables> <TestableReference @@ -66,6 +65,14 @@ BlueprintName = "test" ReferencedContainer = "container:ios.xcodeproj"> </BuildableReference> + <SkippedTests> + <Test + Identifier = "MGLAnnotationViewTests/testAnnotationViewInitWithFrame"> + </Test> + <Test + Identifier = "MGLAnnotationViewTests/testSelectingADisabledAnnotationView"> + </Test> + </SkippedTests> </TestableReference> </Testables> <MacroExpansion> @@ -84,7 +91,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index b7d0974872..c679979d37 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -4290,6 +4290,15 @@ public: moveOnscreen = [self isBringingAnnotationOnscreenSupportedForAnnotation:annotation animated:animateSelection]; } + // If we have an invalid positioning rect, we need to provide a suitable default. + // This (currently) happens if you select an annotation that has NOT yet been + // added. See https://github.com/mapbox/mapbox-gl-native/issues/11476 + if (CGRectIsNull(calloutPositioningRect)) { + CLLocationCoordinate2D origin = annotation.coordinate; + CGPoint originPoint = [self convertCoordinate:origin toPointToView:self]; + calloutPositioningRect = { .origin = originPoint, .size = CGSizeZero }; + } + CGRect expandedPositioningRect = UIEdgeInsetsInsetRect(calloutPositioningRect, MGLMapViewOffscreenAnnotationPadding); // Used for callout positioning, and moving offscreen annotations onscreen. @@ -4442,7 +4451,11 @@ public: { MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation]; CGRect positioningRect = [self positioningRectForCalloutForAnnotationWithTag:annotationTag]; - + + if (CGRectIsNull(positioningRect)) { + return positioningRect; + } + // For annotations which `coordinate` falls offscreen it will use the current tap point as anchor instead. if ( ! CGRectIntersectsRect(positioningRect, self.bounds) && annotation != self.userLocation) { @@ -4462,15 +4475,15 @@ public: id <MGLAnnotation> annotation = [self annotationWithTag:annotationTag]; if ( ! annotation) { - return CGRectZero; + return CGRectNull; } if ([annotation isKindOfClass:[MGLMultiPoint class]]) { CLLocationCoordinate2D origin = annotation.coordinate; CGPoint originPoint = [self convertCoordinate:origin toPointToView:self]; return CGRectMake(originPoint.x, originPoint.y, MGLAnnotationImagePaddingForHitTest, MGLAnnotationImagePaddingForHitTest); - } + UIImage *image = [self imageOfAnnotationWithTag:annotationTag].image; if ( ! image) { @@ -5743,6 +5756,8 @@ public: rect = annotationView.frame; } + NSAssert(!CGRectIsNull(rect), @"Positioning rect should not be CGRectNull by this point"); + CGPoint point = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect)); if ( ! CGPointEqualToPoint(calloutView.center, point)) { diff --git a/platform/ios/test/MGLAnnotationViewTests.m b/platform/ios/test/MGLAnnotationViewTests.m index 2f5963e66e..a2cc4227ed 100644 --- a/platform/ios/test/MGLAnnotationViewTests.m +++ b/platform/ios/test/MGLAnnotationViewTests.m @@ -3,6 +3,13 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReuseIdentifer"; + +@interface MGLMapView (Tests) +@property (nonatomic) MGLCameraChangeReason cameraChangeReasonBitmask; +@end + + + @interface MGLCustomAnnotationView : MGLAnnotationView @end @@ -58,6 +65,7 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu @property (nonatomic) MGLMapView *mapView; @property (nonatomic, weak) MGLAnnotationView *annotationView; @property (nonatomic) NSInteger annotationSelectedCount; +@property (nonatomic) void (^prepareAnnotationView)(MGLAnnotationView*); @end @implementation MGLAnnotationViewTests @@ -152,6 +160,83 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu XCTAssertEqual(selectionCount, self.annotationSelectedCount, @"-mapView:didSelectAnnotation: should be called for each selection"); } +- (void)testSelectingOnscreenAnnotationThatHasNotBeenAdded { + // See https://github.com/mapbox/mapbox-gl-native/issues/11476 + + // This bug occurs under the following conditions: + // + // - There are content insets (e.g. navigation bar) for the compare against + // CGRectZero (now CGRectNull) + // - annotationView.enabled == NO - Currently this can happen if you use + // `-initWithFrame:` rather than one of the provided initializers + // + + self.prepareAnnotationView = ^(MGLAnnotationView *view) { + view.enabled = NO; + }; + + self.mapView.contentInset = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0); + + MGLCameraChangeReason reasonBefore = self.mapView.cameraChangeReasonBitmask; + XCTAssert(reasonBefore == MGLCameraChangeReasonNone, @"Camera should not have moved at start of test"); + + // Create annotation + MGLPointFeature *point = [[MGLPointFeature alloc] init]; + point.title = NSStringFromSelector(_cmd); + point.coordinate = CLLocationCoordinate2DMake(0.0, 0.0); + + MGLCoordinateBounds coordinateBounds = [self.mapView convertRect:self.mapView.bounds toCoordinateBoundsFromView:self.mapView]; + XCTAssert(MGLCoordinateInCoordinateBounds(point.coordinate, coordinateBounds), @"The test point should be within the visible map view"); + + // Select on screen annotation (DO NOT ADD FIRST). + [self.mapView selectAnnotation:point animated:YES]; + + // Expect - the camera NOT to move. + MGLCameraChangeReason reasonAfter = self.mapView.cameraChangeReasonBitmask; + XCTAssert(reasonAfter == MGLCameraChangeReasonNone, @"Camera should not have moved"); +} + +- (void)checkDefaultPropertiesForAnnotationView:(MGLAnnotationView*)view { + XCTAssertNil(view.annotation); + XCTAssertNil(view.reuseIdentifier); + XCTAssertEqual(view.centerOffset.dx, 0.0); + XCTAssertEqual(view.centerOffset.dy, 0.0); + XCTAssertFalse(view.scalesWithViewingDistance); + XCTAssertFalse(view.rotatesToMatchCamera); + XCTAssertFalse(view.isSelected); + XCTAssert(view.isEnabled); + XCTAssertFalse(view.isDraggable); + XCTAssertEqual(view.dragState, MGLAnnotationViewDragStateNone); +} + +- (void)testAnnotationViewInitWithFrame { + CGRect frame = CGRectMake(10.0, 10.0, 100.0, 100.0); + MGLAnnotationView *view = [[MGLAnnotationView alloc] initWithFrame:frame]; + [self checkDefaultPropertiesForAnnotationView:view]; +} + +- (void)testAnnotationViewInitWithReuseIdentifier { + MGLAnnotationView *view = [[MGLAnnotationView alloc] initWithReuseIdentifier:nil]; + [self checkDefaultPropertiesForAnnotationView:view]; +} + +- (void)testSelectingADisabledAnnotationView { + self.prepareAnnotationView = ^(MGLAnnotationView *view) { + view.enabled = NO; + }; + + // Create annotation + MGLPointFeature *point = [[MGLPointFeature alloc] init]; + point.title = NSStringFromSelector(_cmd); + point.coordinate = CLLocationCoordinate2DMake(0.0, 0.0); + + XCTAssert(self.mapView.selectedAnnotations.count == 0, @"There should be 0 selected annotations"); + + [self.mapView selectAnnotation:point animated:NO]; + + XCTAssert(self.mapView.selectedAnnotations.count == 0, @"There should be 0 selected annotations"); +} + #pragma mark - MGLMapViewDelegate - - (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id<MGLAnnotation>)annotation @@ -163,6 +248,10 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu annotationView = [[MGLAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MGLTestAnnotationReuseIdentifer]; } + if (self.prepareAnnotationView) { + self.prepareAnnotationView(annotationView); + } + _annotationView = annotationView; return annotationView; |