diff options
author | Lloyd Sheng <i@lloydsheng.com> | 2019-03-20 15:41:56 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-20 15:41:56 +0800 |
commit | dab3ab79ad54194590a82231cea55940e377e551 (patch) | |
tree | 0f6e3f96746e5765d39e8fc411262f85109971c5 | |
parent | cd0ea372ea06f2f43577644c033c8a974801f3b9 (diff) | |
download | qtlocation-mapboxgl-dab3ab79ad54194590a82231cea55940e377e551.tar.gz |
[ios] Cherry-pick PR #13911 to adding options to customize positions of mapview ornaments (#13863)
* Cherry-pick PR #13556 to adding options to customize positions of mapbox ornaments
-rw-r--r-- | platform/ios/CHANGELOG.md | 3 | ||||
-rw-r--r-- | platform/ios/app/MBXOrnamentsViewController.h | 5 | ||||
-rw-r--r-- | platform/ios/app/MBXOrnamentsViewController.m | 94 | ||||
-rw-r--r-- | platform/ios/app/MBXViewController.m | 11 | ||||
-rw-r--r-- | platform/ios/ios.xcodeproj/project.pbxproj | 6 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.h | 58 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 469 | ||||
-rw-r--r-- | platform/ios/src/MGLScaleBar.mm | 25 | ||||
-rw-r--r-- | platform/ios/test/MGLMapViewLayoutTests.m | 139 | ||||
-rw-r--r-- | platform/ios/test/MGLMapViewScaleBarTests.m | 4 |
10 files changed, 608 insertions, 206 deletions
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index ba8ea3e2d4..eead0b5621 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -5,6 +5,9 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * `MGLMapSnapshotter` now follows "MGLIdeographicFontFamilyName" app setting to reduce font data usage while snapshotting CJK maps [#13427](https://github.com/mapbox/mapbox-gl-native/pull/13427) +## v4.5.0-cn.2 +* Added options to customize position of scale bar, compass, logo and attribution. ([#13863](https://github.com/mapbox/mapbox-gl-native/pull/13863)) + ## v4.5.0-cn.1 * Restored iOS 8 support for the Mapbox Maps SDK for iOS. ([#13036](https://github.com/mapbox/mapbox-gl-native/pull/13036)) diff --git a/platform/ios/app/MBXOrnamentsViewController.h b/platform/ios/app/MBXOrnamentsViewController.h new file mode 100644 index 0000000000..087101cdc0 --- /dev/null +++ b/platform/ios/app/MBXOrnamentsViewController.h @@ -0,0 +1,5 @@ +#import <UIKit/UIKit.h> + +@interface MBXOrnamentsViewController : UIViewController + +@end diff --git a/platform/ios/app/MBXOrnamentsViewController.m b/platform/ios/app/MBXOrnamentsViewController.m new file mode 100644 index 0000000000..45288af0ab --- /dev/null +++ b/platform/ios/app/MBXOrnamentsViewController.m @@ -0,0 +1,94 @@ +#import "MBXOrnamentsViewController.h" + +@import Mapbox; + +@interface MBXOrnamentsViewController ()<MGLMapViewDelegate> + +@property (nonatomic) MGLMapView *mapView; +@property (nonatomic) NSTimer *timer; +@property (nonatomic) NSInteger currentPositionIndex; + +@end + +@implementation MBXOrnamentsViewController + +- (void)setCurrentPositionIndex:(NSInteger)currentPositionIndex { + MGLOrnamentPosition ornamentPositions[5][4] = { + { + MGLOrnamentPositionTopLeft, + MGLOrnamentPositionTopRight, + MGLOrnamentPositionBottomRight, + MGLOrnamentPositionBottomLeft + }, + { + MGLOrnamentPositionTopRight, + MGLOrnamentPositionBottomRight, + MGLOrnamentPositionBottomLeft, + MGLOrnamentPositionTopLeft + }, + { + MGLOrnamentPositionBottomRight, + MGLOrnamentPositionBottomLeft, + MGLOrnamentPositionTopLeft, + MGLOrnamentPositionTopRight + }, + { + MGLOrnamentPositionBottomLeft, + MGLOrnamentPositionTopLeft, + MGLOrnamentPositionTopRight, + MGLOrnamentPositionBottomRight + }, + { + MGLOrnamentPositionTopLeft, + MGLOrnamentPositionTopRight, + MGLOrnamentPositionBottomRight, + MGLOrnamentPositionBottomLeft + } + }; + MGLOrnamentPosition *currentPosition = ornamentPositions[currentPositionIndex]; + self.mapView.scaleBarPosition = currentPosition[0]; + self.mapView.compassViewPosition = currentPosition[1]; + self.mapView.logoViewPosition = currentPosition[2]; + self.mapView.attributionButtonPosition = currentPosition[3]; + + _currentPositionIndex = currentPositionIndex; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + self.title = @"Ornaments"; + + MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:self.view.frame]; + mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [mapView setCenterCoordinate:CLLocationCoordinate2DMake(39.915143, 116.404053) + zoomLevel:16 + direction:30 + animated:NO]; + mapView.delegate = self; + mapView.showsScale = YES; + [self.view addSubview:mapView]; + + self.mapView = mapView; +} + +- (void)viewDidDisappear:(BOOL)animated { + [self.timer invalidate]; + self.timer = nil; +} + +- (void)viewDidAppear:(BOOL)animated { + self.timer = [NSTimer scheduledTimerWithTimeInterval:1 + target:self + selector:@selector(onTimerTick) + userInfo:nil + repeats:YES]; +} + +- (void)onTimerTick { + self.currentPositionIndex ++; + if (self.currentPositionIndex >= 4) { + self.currentPositionIndex = 0; + } +} + +@end diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 42bfd01d42..370369067d 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -7,6 +7,7 @@ #import "MBXUserLocationAnnotationView.h" #import "LimeGreenStyleLayer.h" #import "MBXEmbeddedMapViewController.h" +#import "MBXOrnamentsViewController.h" #import <Mapbox/Mapbox.h> #import "../src/MGLMapView_Experimental.h" @@ -100,8 +101,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { MBXSettingsMiscellaneousShowSnapshots, MBXSettingsMiscellaneousShouldLimitCameraChanges, MBXSettingsMiscellaneousShowCustomLocationManager, + MBXSettingsMiscellaneousOrnamentsPlacement, MBXSettingsMiscellaneousPrintLogFile, - MBXSettingsMiscellaneousDeleteLogFile, + MBXSettingsMiscellaneousDeleteLogFile }; // Utility methods @@ -462,6 +464,7 @@ CLLocationCoordinate2D randomWorldCoordinate() { @"Show Snapshots", [NSString stringWithFormat:@"%@ Camera Changes", (_shouldLimitCameraChanges ? @"Unlimit" : @"Limit")], @"View Route Simulation", + @"Ornaments Placement", ]]; if (self.debugLoggingEnabled) @@ -713,6 +716,12 @@ CLLocationCoordinate2D randomWorldCoordinate() { } break; } + case MBXSettingsMiscellaneousOrnamentsPlacement: + { + MBXOrnamentsViewController *ornamentsViewController = [[MBXOrnamentsViewController alloc] init]; + [self.navigationController pushViewController:ornamentsViewController animated:YES]; + break; + } default: NSAssert(NO, @"All miscellaneous setting rows should be implemented"); break; diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 76f09e0948..903a8ffa49 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -294,6 +294,7 @@ 55E2AD131E5B125400E8C587 /* MGLOfflineStorageTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 55E2AD121E5B125400E8C587 /* MGLOfflineStorageTests.mm */; }; 632281DF1E6F855900D75A5D /* MBXEmbeddedMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 632281DE1E6F855900D75A5D /* MBXEmbeddedMapViewController.m */; }; 6407D6701E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */; }; + 6FA9341721EF372100AA9CA8 /* MBXOrnamentsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FA9341521EF372100AA9CA8 /* MBXOrnamentsViewController.m */; }; 8989B17C201A48EB0081CF59 /* MGLHeatmapStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8989B17A201A48EA0081CF59 /* MGLHeatmapStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8989B17D201A48EB0081CF59 /* MGLHeatmapStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8989B17A201A48EA0081CF59 /* MGLHeatmapStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8989B17E201A48EB0081CF59 /* MGLHeatmapStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8989B17B201A48EA0081CF59 /* MGLHeatmapStyleLayer.mm */; }; @@ -976,6 +977,8 @@ 632281DD1E6F855900D75A5D /* MBXEmbeddedMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXEmbeddedMapViewController.h; sourceTree = "<group>"; }; 632281DE1E6F855900D75A5D /* MBXEmbeddedMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXEmbeddedMapViewController.m; sourceTree = "<group>"; }; 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLDocumentationExampleTests.swift; path = ../../darwin/test/MGLDocumentationExampleTests.swift; sourceTree = "<group>"; }; + 6FA9341521EF372100AA9CA8 /* MBXOrnamentsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXOrnamentsViewController.m; sourceTree = "<group>"; }; + 6FA9341621EF372100AA9CA8 /* MBXOrnamentsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXOrnamentsViewController.h; sourceTree = "<group>"; }; 8989B17A201A48EA0081CF59 /* MGLHeatmapStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLHeatmapStyleLayer.h; sourceTree = "<group>"; }; 8989B17B201A48EA0081CF59 /* MGLHeatmapStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLHeatmapStyleLayer.mm; sourceTree = "<group>"; }; 920A3E5C1E6F995200C16EFC /* MGLSourceQueryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLSourceQueryTests.m; path = ../../darwin/test/MGLSourceQueryTests.m; sourceTree = "<group>"; }; @@ -1806,6 +1809,8 @@ DA1DC99A1CB6E064006E619F /* MBXViewController.m */, 632281DD1E6F855900D75A5D /* MBXEmbeddedMapViewController.h */, 632281DE1E6F855900D75A5D /* MBXEmbeddedMapViewController.m */, + 6FA9341621EF372100AA9CA8 /* MBXOrnamentsViewController.h */, + 6FA9341521EF372100AA9CA8 /* MBXOrnamentsViewController.m */, DA821D051CCC6D59007508D4 /* Main.storyboard */, DA821D041CCC6D59007508D4 /* LaunchScreen.storyboard */, DA1DC99E1CB6E088006E619F /* Assets.xcassets */, @@ -2852,6 +2857,7 @@ DA1DC9971CB6E046006E619F /* main.m in Sources */, 354B839C1D2E9B48005D9406 /* MBXUserLocationAnnotationView.m in Sources */, DA1DC9991CB6E054006E619F /* MBXAppDelegate.m in Sources */, + 6FA9341721EF372100AA9CA8 /* MBXOrnamentsViewController.m in Sources */, DA1DC96B1CB6C6B7006E619F /* MBXOfflinePacksTableViewController.m in Sources */, DA1DC96A1CB6C6B7006E619F /* MBXCustomCalloutView.m in Sources */, 927FBCFC1F4DAA8300F8BF1F /* MBXSnapshotsViewController.m in Sources */, diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h index 5312804cd2..3678f755ee 100644 --- a/platform/ios/src/MGLMapView.h +++ b/platform/ios/src/MGLMapView.h @@ -49,6 +49,24 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationVerticalAlignment) { }; /** + The position of scale bar, compass, logo and attribution in a map view. Used with + `MGLMapView.scaleBarPosition`, + `MGLMapView.compassViewPosition`, + `MGLMapView.logoViewPosition`, + `MGLMapView.attributionButtonPosition`. + */ +typedef NS_ENUM(NSUInteger, MGLOrnamentPosition) { + /** Place the ornament in the top left of the map view. */ + MGLOrnamentPositionTopLeft = 0, + /** Place the ornament in the top right of the map view. */ + MGLOrnamentPositionTopRight, + /** Place the ornament in the bottom left of the map view. */ + MGLOrnamentPositionBottomLeft, + /** Place the ornament in the bottom right of the map view. */ + MGLOrnamentPositionBottomRight, +}; + +/** The mode used to track the user location on the map. Used with `MGLMapView.userTrackingMode`. */ @@ -258,12 +276,32 @@ MGL_EXPORT IB_DESIGNABLE @property (nonatomic, readonly) UIView *scaleBar; /** + The position of the scale bar. The default value is `MGLOrnamentPositionTopLeft`. + */ +@property (nonatomic, assign) MGLOrnamentPosition scaleBarPosition; + +/** + A `CGPoint` indicating the position offset of the scale bar. + */ +@property (nonatomic, assign) CGPoint scaleBarMargins; + +/** A control indicating the map’s direction and allowing the user to manipulate the direction, positioned in the upper-right corner. */ @property (nonatomic, readonly) UIImageView *compassView; /** + The position of the compass view. The default value is `MGLOrnamentPositionTopRight`. + */ +@property (nonatomic, assign) MGLOrnamentPosition compassViewPosition; + +/** + A `CGPoint` indicating the position offset of the compass. + */ +@property (nonatomic, assign) CGPoint compassViewMargins; + +/** The Mapbox logo, positioned in the lower-left corner. @note The Mapbox terms of service, which governs the use of Mapbox-hosted @@ -275,6 +313,16 @@ MGL_EXPORT IB_DESIGNABLE @property (nonatomic, readonly) UIImageView *logoView; /** + The position of the logo view. The default value is `MGLOrnamentPositionBottomLeft`. + */ +@property (nonatomic, assign) MGLOrnamentPosition logoViewPosition; + +/** + A `CGPoint` indicating the position offset of the logo. + */ +@property (nonatomic, assign) CGPoint logoViewMargins; + +/** A view showing legally required copyright notices and telemetry settings, positioned at the bottom-right of the map view. @@ -300,6 +348,16 @@ MGL_EXPORT IB_DESIGNABLE @property (nonatomic, readonly) UIButton *attributionButton; /** + The position of the attribution button. The default value is `MGLOrnamentPositionBottomRight`. + */ +@property (nonatomic, assign) MGLOrnamentPosition attributionButtonPosition; + +/** + A `CGPoint` indicating the position offset of the attribution. + */ +@property (nonatomic, assign) CGPoint attributionButtonMargins; + +/** Show the attribution and telemetry action sheet. This action is performed when the user taps on the attribution button provided diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index a65ece1c6b..3a786e54d0 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -96,6 +96,8 @@ const MGLExceptionName MGLMissingLocationServicesUsageDescriptionException = @"M const MGLExceptionName MGLUserLocationAnnotationTypeException = @"MGLUserLocationAnnotationTypeException"; const MGLExceptionName MGLResourceNotFoundException = @"MGLResourceNotFoundException"; +const CGPoint MGLOrnamentDefaultPositionOffset = CGPointMake(8, 8); + /// Indicates the manner in which the map view is tracking the user location. typedef NS_ENUM(NSUInteger, MGLUserTrackingState) { /// The map view is not yet tracking the user location. @@ -479,6 +481,8 @@ public: _logoView.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:_logoView]; _logoViewConstraints = [NSMutableArray array]; + _logoViewPosition = MGLOrnamentPositionBottomLeft; + _logoViewMargins = MGLOrnamentDefaultPositionOffset; // setup attribution // @@ -493,6 +497,8 @@ public: UILongPressGestureRecognizer *attributionLongPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showAttribution:)]; [_attributionButton addGestureRecognizer:attributionLongPress]; + _attributionButtonPosition = MGLOrnamentPositionBottomRight; + _attributionButtonMargins = MGLOrnamentDefaultPositionOffset; // setup compass // @@ -506,6 +512,8 @@ public: _compassView.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:_compassView]; _compassViewConstraints = [NSMutableArray array]; + _compassViewPosition = MGLOrnamentPositionTopRight; + _compassViewMargins = MGLOrnamentDefaultPositionOffset; // setup scale control // @@ -513,7 +521,11 @@ public: _scaleBar.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:_scaleBar]; _scaleBarConstraints = [NSMutableArray array]; - + _scaleBarPosition = MGLOrnamentPositionTopLeft; + _scaleBarMargins = MGLOrnamentDefaultPositionOffset; + + [self installConstraints]; + // setup interaction // _pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; @@ -757,6 +769,46 @@ public: return YES; } +- (void)setScaleBarPosition:(MGLOrnamentPosition)scaleBarPosition { + _scaleBarPosition = scaleBarPosition; + [self installScaleBarConstraints]; +} + +- (void)setScaleBarMargins:(CGPoint)scaleBarOffset { + _scaleBarMargins = scaleBarOffset; + [self installScaleBarConstraints]; +} + +- (void)setCompassViewPosition:(MGLOrnamentPosition)compassViewPosition { + _compassViewPosition = compassViewPosition; + [self installCompassViewConstraints]; +} + +- (void)setCompassViewMargins:(CGPoint)compassViewOffset { + _compassViewMargins = compassViewOffset; + [self installCompassViewConstraints]; +} + +- (void)setLogoViewPosition:(MGLOrnamentPosition)logoViewPosition { + _logoViewPosition = logoViewPosition; + [self installLogoViewConstraints]; +} + +- (void)setLogoViewMargins:(CGPoint)logoViewOffset { + _logoViewMargins = logoViewOffset; + [self installLogoViewConstraints]; +} + +- (void)setAttributionButtonPosition:(MGLOrnamentPosition)attributionButtonPosition { + _attributionButtonPosition = attributionButtonPosition; + [self installAttributionButtonConstraints]; +} + +- (void)setAttributionButtonMargins:(CGPoint)attributionButtonOffset { + _attributionButtonMargins = attributionButtonOffset; + [self installAttributionButtonConstraints]; +} + - (UIViewController *)viewControllerForLayoutGuides { // Per -[UIResponder nextResponder] documentation, a UIView’s next responder @@ -775,204 +827,239 @@ public: return nil; } -- (void)updateConstraintsPreiOS11 { - // If we have a view controller reference and its automaticallyAdjustsScrollViewInsets - // is set to YES, use its view as the parent for constraints. -[MGLMapView adjustContentInset] - // already take top and bottom layout guides into account. If we don't have a reference, apply - // constraints against ourself to maintain placement of the subviews. - // - UIViewController *viewController = self.viewControllerForLayoutGuides; - BOOL useLayoutGuides = viewController.view && viewController.automaticallyAdjustsScrollViewInsets; - UIView *containerView = useLayoutGuides ? viewController.view : self; - - // compass view - // - [containerView removeConstraints:self.compassViewConstraints]; - [self.compassViewConstraints removeAllObjects]; - - if (useLayoutGuides) { - [self.compassViewConstraints addObject: - [NSLayoutConstraint constraintWithItem:self.compassView - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:viewController.topLayoutGuide - attribute:NSLayoutAttributeBottom - multiplier:1.0 - constant:8.0]]; - } - [self.compassViewConstraints addObject: - [NSLayoutConstraint constraintWithItem:self.compassView - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:self - attribute:NSLayoutAttributeTop - multiplier:1.0 - constant:8.0 + self.contentInset.top]]; - - [self.compassViewConstraints addObject: - [NSLayoutConstraint constraintWithItem:self - attribute:NSLayoutAttributeTrailing - relatedBy:NSLayoutRelationEqual - toItem:self.compassView - attribute:NSLayoutAttributeTrailing - multiplier:1.0 - constant:8.0 + self.contentInset.right]]; +- (void)updateConstraintsForOrnament:(UIView *)view + constraints:(NSMutableArray *)constraints + position:(MGLOrnamentPosition)position + size:(CGSize)size + offset:(CGPoint)offset { + NSMutableArray *updatedConstraints = [NSMutableArray array]; - [containerView addConstraints:self.compassViewConstraints]; - - // scale bar view - // - [containerView removeConstraints:self.scaleBarConstraints]; - [self.scaleBarConstraints removeAllObjects]; - - if (useLayoutGuides) { - [self.scaleBarConstraints addObject: - [NSLayoutConstraint constraintWithItem:self.scaleBar - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:viewController.topLayoutGuide - attribute:NSLayoutAttributeBottom + if (@available(iOS 11.0, *)) { + UILayoutGuide *safeAreaLayoutGuide = self.safeAreaLayoutGuide; + + switch (position) { + case MGLOrnamentPositionTopLeft: + [updatedConstraints addObject:[view.topAnchor constraintEqualToAnchor:safeAreaLayoutGuide.topAnchor constant:offset.y]]; + [updatedConstraints addObject:[view.leftAnchor constraintEqualToAnchor:safeAreaLayoutGuide.leftAnchor constant:offset.x]]; + break; + case MGLOrnamentPositionTopRight: + [updatedConstraints addObject:[view.topAnchor constraintEqualToAnchor:safeAreaLayoutGuide.topAnchor constant:offset.y]]; + [updatedConstraints addObject:[safeAreaLayoutGuide.rightAnchor constraintEqualToAnchor:view.rightAnchor constant:offset.x]]; + break; + case MGLOrnamentPositionBottomLeft: + [updatedConstraints addObject:[safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:view.bottomAnchor constant:offset.y]]; + [updatedConstraints addObject:[view.leftAnchor constraintEqualToAnchor:safeAreaLayoutGuide.leftAnchor constant:offset.x]]; + break; + case MGLOrnamentPositionBottomRight: + [updatedConstraints addObject:[safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:view.bottomAnchor constant:offset.y]]; + [updatedConstraints addObject: [safeAreaLayoutGuide.rightAnchor constraintEqualToAnchor:view.rightAnchor constant:offset.x]]; + break; + + default: + break; + } + [updatedConstraints addObject:[view.widthAnchor constraintEqualToConstant:size.width]]; + [updatedConstraints addObject:[view.heightAnchor constraintEqualToConstant:size.height]]; + } else { + // If we have a view controller reference and its automaticallyAdjustsScrollViewInsets + // is set to YES, use its view as the parent for constraints. -[MGLMapView adjustContentInset] + // already take top and bottom layout guides into account. If we don't have a reference, apply + // constraints against ourself to maintain placement of the subviews. + // + UIViewController *viewController = self.viewControllerForLayoutGuides; + BOOL useLayoutGuides = viewController.view && viewController.automaticallyAdjustsScrollViewInsets; + + switch (position) { + case MGLOrnamentPositionTopLeft: + if (useLayoutGuides) { + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:viewController.topLayoutGuide + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:offset.y]]; + } + else { + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:offset.y]]; + } + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:offset.x]]; + break; + case MGLOrnamentPositionTopRight: + if (useLayoutGuides) { + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:viewController.topLayoutGuide + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:offset.y]]; + } + else { + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:offset.y]]; + } + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:view + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:offset.x]]; + break; + case MGLOrnamentPositionBottomLeft: + if (useLayoutGuides) { + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:viewController.bottomLayoutGuide + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:view + attribute:NSLayoutAttributeBaseline + multiplier:1.0 + constant:offset.y]]; + } + else { + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:view + attribute:NSLayoutAttributeBaseline + multiplier:1 + constant:offset.y]]; + } + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:offset.x]]; + break; + case MGLOrnamentPositionBottomRight: + if (useLayoutGuides) { + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:viewController.bottomLayoutGuide + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:view + attribute:NSLayoutAttributeBaseline + multiplier:1 + constant:offset.y]]; + } + else { + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:view + attribute:NSLayoutAttributeBaseline + multiplier:1 + constant:offset.y]]; + } + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:view + attribute:NSLayoutAttributeTrailing + multiplier:1 + constant:offset.x]]; + break; + + default: + break; + } + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 - constant:8.0]]; - } - [self.scaleBarConstraints addObject: - [NSLayoutConstraint constraintWithItem:self.scaleBar - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:self - attribute:NSLayoutAttributeTop - multiplier:1.0 - constant:8.0 + self.contentInset.top]]; - [self.scaleBarConstraints addObject: - [NSLayoutConstraint constraintWithItem:self.scaleBar - attribute:NSLayoutAttributeLeft - relatedBy:NSLayoutRelationEqual - toItem:self - attribute:NSLayoutAttributeLeft - multiplier:1.0 - constant:8.0 + self.contentInset.left]]; - - [containerView addConstraints:self.scaleBarConstraints]; - - // logo view - // - [containerView removeConstraints:self.logoViewConstraints]; - [self.logoViewConstraints removeAllObjects]; - - if (useLayoutGuides) { - [self.logoViewConstraints addObject: - [NSLayoutConstraint constraintWithItem:viewController.bottomLayoutGuide - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:self.logoView - attribute:NSLayoutAttributeBaseline + constant:size.width]]; + [updatedConstraints addObject: + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 - constant:8.0 + self.contentInset.bottom]]; + constant:size.height]]; } - [self.logoViewConstraints addObject: - [NSLayoutConstraint constraintWithItem:self - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:self.logoView - attribute:NSLayoutAttributeBaseline - multiplier:1 - constant:8.0 + self.contentInset.bottom]]; - [self.logoViewConstraints addObject: - [NSLayoutConstraint constraintWithItem:self.logoView - attribute:NSLayoutAttributeLeading - relatedBy:NSLayoutRelationEqual - toItem:self - attribute:NSLayoutAttributeLeading - multiplier:1.0 - constant:8.0 + self.contentInset.left]]; - [containerView addConstraints:self.logoViewConstraints]; - - // attribution button - // - [containerView removeConstraints:self.attributionButtonConstraints]; - [self.attributionButtonConstraints removeAllObjects]; - - if (useLayoutGuides) { - [self.attributionButtonConstraints addObject: - [NSLayoutConstraint constraintWithItem:viewController.bottomLayoutGuide - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:self.attributionButton - attribute:NSLayoutAttributeBaseline - multiplier:1 - constant:8.0 + self.contentInset.bottom]]; - } - [self.attributionButtonConstraints addObject: - [NSLayoutConstraint constraintWithItem:self - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationGreaterThanOrEqual - toItem:self.attributionButton - attribute:NSLayoutAttributeBaseline - multiplier:1 - constant:8.0 + self.contentInset.bottom]]; - - [self.attributionButtonConstraints addObject: - [NSLayoutConstraint constraintWithItem:self - attribute:NSLayoutAttributeTrailing - relatedBy:NSLayoutRelationEqual - toItem:self.attributionButton - attribute:NSLayoutAttributeTrailing - multiplier:1 - constant:8.0 + self.contentInset.right]]; - [containerView addConstraints:self.attributionButtonConstraints]; + + [NSLayoutConstraint deactivateConstraints:constraints]; + [constraints removeAllObjects]; + [NSLayoutConstraint activateConstraints:updatedConstraints]; + [constraints addObjectsFromArray:updatedConstraints]; } -- (void)updateConstraints +- (void)installConstraints { - // If safeAreaLayoutGuide API exists - if (@available(iOS 11.0, *)) { - UILayoutGuide *safeAreaLayoutGuide = self.safeAreaLayoutGuide; + [self installCompassViewConstraints]; + [self installScaleBarConstraints]; + [self installLogoViewConstraints]; + [self installAttributionButtonConstraints]; +} - // compass view - [self removeConstraints:self.compassViewConstraints]; - [self.compassViewConstraints removeAllObjects]; - [self.compassViewConstraints addObject:[self constraintForYAxisAnchor:self.compassView.topAnchor belowAnchor:safeAreaLayoutGuide.topAnchor]]; - [self.compassViewConstraints addObject:[safeAreaLayoutGuide.rightAnchor constraintEqualToAnchor:self.compassView.rightAnchor - constant:8.0 + self.contentInset.right]]; - [self addConstraints:self.compassViewConstraints]; - - // scale bar view - [self removeConstraints:self.scaleBarConstraints]; - [self.scaleBarConstraints removeAllObjects]; - [self.scaleBarConstraints addObject:[self constraintForYAxisAnchor:self.scaleBar.topAnchor belowAnchor:safeAreaLayoutGuide.topAnchor]]; - [self.scaleBarConstraints addObject:[self.scaleBar.leftAnchor constraintEqualToAnchor:safeAreaLayoutGuide.leftAnchor - constant:8.0 + self.contentInset.left]]; - [self addConstraints:self.scaleBarConstraints]; - - // logo view - [self removeConstraints:self.logoViewConstraints]; - [self.logoViewConstraints removeAllObjects]; - [self.logoViewConstraints addObject:[self constraintForYAxisAnchor:safeAreaLayoutGuide.bottomAnchor belowAnchor:self.logoView.bottomAnchor]]; - [self.logoViewConstraints addObject:[self.logoView.leftAnchor constraintEqualToAnchor:safeAreaLayoutGuide.leftAnchor - constant:8.0 + self.contentInset.left]]; - [self addConstraints:self.logoViewConstraints]; - - // attribution button - [self removeConstraints:self.attributionButtonConstraints]; - [self.attributionButtonConstraints removeAllObjects]; - [self.attributionButtonConstraints addObject:[self constraintForYAxisAnchor:safeAreaLayoutGuide.bottomAnchor belowAnchor:self.attributionButton.bottomAnchor]]; - [self.attributionButtonConstraints addObject:[safeAreaLayoutGuide.rightAnchor constraintEqualToAnchor:self.attributionButton.rightAnchor - constant:8.0 + self.contentInset.right]]; - [self addConstraints:self.attributionButtonConstraints]; - } else { - [self updateConstraintsPreiOS11]; - } - - [super updateConstraints]; +- (void)installCompassViewConstraints { + // compass view + [self updateConstraintsForOrnament:self.compassView + constraints:self.compassViewConstraints + position:self.compassViewPosition + size:self.compassView.bounds.size + offset:self.compassViewMargins]; } -- (NSLayoutConstraint *)constraintForYAxisAnchor:(NSLayoutYAxisAnchor *)yAxisAnchor belowAnchor:(NSLayoutYAxisAnchor *)anchor -{ - if (@available(iOS 11.0, *)) { - return [yAxisAnchor constraintEqualToSystemSpacingBelowAnchor:anchor multiplier:1]; - } else { - return nil; - } +- (void)installScaleBarConstraints { + // scale bar view + [self updateConstraintsForOrnament:self.scaleBar + constraints:self.scaleBarConstraints + position:self.scaleBarPosition + size:self.scaleBar.intrinsicContentSize + offset:self.scaleBarMargins]; +} + +- (void)installLogoViewConstraints { + // logo view + [self updateConstraintsForOrnament:self.logoView + constraints:self.logoViewConstraints + position:self.logoViewPosition + size:self.logoView.bounds.size + offset:self.logoViewMargins]; +} + +- (void)installAttributionButtonConstraints { + // attribution button + [self updateConstraintsForOrnament:self.attributionButton + constraints:self.attributionButtonConstraints + position:self.attributionButtonPosition + size:self.attributionButton.bounds.size + offset:self.attributionButtonMargins]; } - (BOOL)isOpaque @@ -1095,7 +1182,7 @@ public: } // Compass, logo and attribution button constraints needs to be updated. - [self setNeedsUpdateConstraints]; + [self installConstraints]; } /// Returns the frame of inset content within the map view. @@ -1249,6 +1336,7 @@ public: - (void)didMoveToSuperview { [self validateDisplayLink]; + [self installConstraints]; [super didMoveToSuperview]; } @@ -6085,6 +6173,7 @@ public: if ( ! self.scaleBar.hidden) { [(MGLScaleBar *)self.scaleBar setMetersPerPoint:[self metersPerPointAtLatitude:self.centerCoordinate.latitude]]; + [self installScaleBarConstraints]; } } diff --git a/platform/ios/src/MGLScaleBar.mm b/platform/ios/src/MGLScaleBar.mm index a180280adc..c39fce8ce6 100644 --- a/platform/ios/src/MGLScaleBar.mm +++ b/platform/ios/src/MGLScaleBar.mm @@ -86,7 +86,7 @@ static const MGLRow MGLImperialTable[] ={ @property (nonatomic, assign) CGFloat borderWidth; @property (nonatomic) NSCache* labelImageCache; @property (nonatomic) MGLScaleBarLabel* prototypeLabel; - +@property (nonatomic) CGFloat lastLabelWidth; @end @@ -94,6 +94,7 @@ static const CGFloat MGLBarHeight = 4; static const CGFloat MGLFeetPerMeter = 3.28084; @interface MGLScaleBarLabel : UILabel + @end @implementation MGLScaleBarLabel @@ -184,7 +185,7 @@ static const CGFloat MGLFeetPerMeter = 3.28084; #pragma mark - Dimensions - (CGSize)intrinsicContentSize { - return CGSizeMake(self.actualWidth, 16); + return self.actualWidth > 0 ? CGSizeMake(ceil(self.actualWidth + self.lastLabelWidth/2), 16) : CGSizeZero; } - (CGFloat)actualWidth { @@ -194,8 +195,7 @@ static const CGFloat MGLFeetPerMeter = 3.28084; - (CGFloat)maximumWidth { CGFloat fullWidth = CGRectGetWidth(self.superview.bounds); - CGFloat padding = [self usesRightToLeftLayout] ? fullWidth - CGRectGetMaxX(self.frame) : CGRectGetMinX(self.frame); - return floorf(fullWidth / 2 - padding); + return floorf(fullWidth / 2); } - (CGFloat)unitsPerPoint { @@ -261,11 +261,8 @@ static const CGFloat MGLFeetPerMeter = 3.28084; self.row = [self preferredRow]; - CGSize size = self.intrinsicContentSize; - self.frame = CGRectMake(CGRectGetMinX(self.frame), - CGRectGetMinY(self.frame), - size.width, - size.height); + [self invalidateIntrinsicContentSize]; + [self setNeedsLayout]; } - (void)updateVisibility { @@ -375,7 +372,9 @@ static const CGFloat MGLFeetPerMeter = 3.28084; CLLocationDistance barDistance = multiplier * i; UIImage *image = [self cachedLabelImageForDistance:barDistance]; - + if (i == self.row.numberOfBars) { + self.lastLabelWidth = image.size.width; + } labelView.layer.contents = (id)image.CGImage; labelView.layer.contentsScale = image.scale; } @@ -413,7 +412,7 @@ static const CGFloat MGLFeetPerMeter = 3.28084; } self.containerView.frame = CGRectMake(CGRectGetMinX(self.bars.firstObject.frame), - CGRectGetMaxY(self.bounds)-MGLBarHeight, + self.intrinsicContentSize.height-MGLBarHeight, self.actualWidth, MGLBarHeight+self.borderWidth*2); @@ -425,12 +424,12 @@ static const CGFloat MGLFeetPerMeter = 3.28084; } - (void)layoutLabels { - CGFloat barWidth = round(self.bounds.size.width / self.bars.count); + CGFloat barWidth = round(self.actualWidth / self.bars.count); BOOL RTL = [self usesRightToLeftLayout]; NSUInteger i = RTL ? self.bars.count : 0; for (UIView *label in self.labelViews) { CGFloat xPosition = round(barWidth * i - CGRectGetMidX(label.bounds) + self.borderWidth); - CGFloat yPosition = round(0.5 * (CGRectGetMaxY(self.bounds) - MGLBarHeight)); + CGFloat yPosition = round(0.5 * (self.intrinsicContentSize.height - MGLBarHeight)); CGRect frame = label.frame; frame.origin.x = xPosition; diff --git a/platform/ios/test/MGLMapViewLayoutTests.m b/platform/ios/test/MGLMapViewLayoutTests.m index 4bdff51e25..d902665768 100644 --- a/platform/ios/test/MGLMapViewLayoutTests.m +++ b/platform/ios/test/MGLMapViewLayoutTests.m @@ -4,6 +4,27 @@ #import "MGLAccountManager.h" +@interface MGLOrnamentTestData : NSObject + +@property (nonatomic) MGLOrnamentPosition position; +@property (nonatomic) CGPoint margins; +@property (nonatomic) CGPoint expectedOrigin; + +@end + +@implementation MGLOrnamentTestData + ++ (instancetype)createWithPostion:(MGLOrnamentPosition)position offset:(CGPoint)offset expectedOrigin:(CGPoint)expectedOrigin { + MGLOrnamentTestData *data = [[MGLOrnamentTestData alloc] init]; + data.position = position; + data.margins = offset; + data.expectedOrigin = expectedOrigin; + return data; +} + +@end + + @interface MGLMapViewLayoutTests : XCTestCase<MGLMapViewDelegate> @property (nonatomic) UIView *superView; @@ -106,4 +127,122 @@ XCTAssertEqualWithAccuracy(CGRectGetMinY(logoView.frame), expectedLogoOriginY, accuracy); } +- (NSArray *)makeTestDataListWithView:(UIView *)view margin:(CGFloat)margin { + CGFloat bottomSafeAreaInset = 0.0; + if (@available(iOS 11.0, *)) { + bottomSafeAreaInset = self.mapView.safeAreaInsets.bottom; + } + + return @[ + [MGLOrnamentTestData createWithPostion:MGLOrnamentPositionTopLeft + offset:CGPointMake(margin, margin) + expectedOrigin:CGPointMake(margin, margin)], + [MGLOrnamentTestData createWithPostion:MGLOrnamentPositionTopRight + offset:CGPointMake(margin, margin) + expectedOrigin:CGPointMake(CGRectGetMaxX(self.mapView.bounds) - margin - CGRectGetWidth(view.frame), 4)], + [MGLOrnamentTestData createWithPostion:MGLOrnamentPositionBottomLeft + offset:CGPointMake(margin, margin) + expectedOrigin:CGPointMake(margin, CGRectGetMaxY(self.mapView.bounds) - margin - bottomSafeAreaInset - CGRectGetHeight(view.frame))], + [MGLOrnamentTestData createWithPostion:MGLOrnamentPositionBottomRight + offset:CGPointMake(margin, margin) + expectedOrigin:CGPointMake(CGRectGetMaxX(self.mapView.bounds) - margin - CGRectGetWidth(view.frame), + CGRectGetMaxY(self.mapView.bounds) - margin - bottomSafeAreaInset - CGRectGetHeight(view.frame))] + ]; +} + +- (void)testCompassPlacement { + double accuracy = 0.01; + CGFloat margin = 4.0; + + UIView *compassView = self.mapView.compassView; + NSArray *testDataList = [self makeTestDataListWithView:compassView margin:margin]; + + for (MGLOrnamentTestData *testData in testDataList) { + self.mapView.compassViewPosition = testData.position; + self.mapView.compassViewMargins = testData.margins; + + //invoke layout + [self.superView setNeedsLayout]; + [self.superView layoutIfNeeded]; + + XCTAssertEqualWithAccuracy(CGRectGetMinX(compassView.frame), testData.expectedOrigin.x, accuracy); + XCTAssertEqualWithAccuracy(CGRectGetMinY(compassView.frame), testData.expectedOrigin.y, accuracy); + } +} + +- (void)testScalebarPlacement { + CGFloat bottomSafeAreaInset = 0.0; + double accuracy = 0.01; + CGFloat margin = 4.0; + + if (@available(iOS 11.0, *)) { + bottomSafeAreaInset = self.mapView.safeAreaInsets.bottom; + } + + UIView *scaleBar = self.mapView.scaleBar; + NSArray *testDataList = [self makeTestDataListWithView:scaleBar margin:margin]; + + for (MGLOrnamentTestData *testData in testDataList) { + self.mapView.scaleBarPosition = testData.position; + self.mapView.scaleBarMargins = testData.margins; + + //invoke layout + [self.superView setNeedsLayout]; + [self.superView layoutIfNeeded]; + + XCTAssertEqualWithAccuracy(CGRectGetMinX(scaleBar.frame), testData.expectedOrigin.x, accuracy); + XCTAssertEqualWithAccuracy(CGRectGetMinY(scaleBar.frame), testData.expectedOrigin.y, accuracy); + } +} + +- (void)testAttributionButtonPlacement { + CGFloat bottomSafeAreaInset = 0.0; + double accuracy = 0.01; + CGFloat margin = 4.0; + + if (@available(iOS 11.0, *)) { + bottomSafeAreaInset = self.mapView.safeAreaInsets.bottom; + } + + UIView *attributionButton = self.mapView.attributionButton; + NSArray *testDataList = [self makeTestDataListWithView:attributionButton margin:margin]; + + for (MGLOrnamentTestData *testData in testDataList) { + self.mapView.attributionButtonPosition = testData.position; + self.mapView.attributionButtonMargins = testData.margins; + + //invoke layout + [self.superView setNeedsLayout]; + [self.superView layoutIfNeeded]; + + XCTAssertEqualWithAccuracy(CGRectGetMinX(attributionButton.frame), testData.expectedOrigin.x, accuracy); + XCTAssertEqualWithAccuracy(CGRectGetMinY(attributionButton.frame), testData.expectedOrigin.y, accuracy); + } +} + +- (void)testLogoPlacement { + CGFloat bottomSafeAreaInset = 0.0; + double accuracy = 0.01; + CGFloat margin = 4.0; + + if (@available(iOS 11.0, *)) { + bottomSafeAreaInset = self.mapView.safeAreaInsets.bottom; + } + + UIView *logoView = self.mapView.logoView; + NSArray *testDataList = [self makeTestDataListWithView:logoView margin:margin]; + + for (MGLOrnamentTestData *testData in testDataList) { + self.mapView.logoViewPosition = testData.position; + self.mapView.logoViewMargins = testData.margins; + + //invoke layout + [self.superView setNeedsLayout]; + [self.superView layoutIfNeeded]; + + XCTAssertEqualWithAccuracy(CGRectGetMinX(logoView.frame), testData.expectedOrigin.x, accuracy); + XCTAssertEqualWithAccuracy(CGRectGetMinY(logoView.frame), testData.expectedOrigin.y, accuracy); + } +} + @end diff --git a/platform/ios/test/MGLMapViewScaleBarTests.m b/platform/ios/test/MGLMapViewScaleBarTests.m index 11d1187263..50864beb4d 100644 --- a/platform/ios/test/MGLMapViewScaleBarTests.m +++ b/platform/ios/test/MGLMapViewScaleBarTests.m @@ -35,7 +35,7 @@ XCTAssertFalse(scaleBar.hidden); // Scale bar should not be visible at default zoom (~z0), but it should be ready. - XCTAssertFalse(CGRectIsEmpty(scaleBar.frame)); + XCTAssertFalse(CGSizeEqualToSize(scaleBar.intrinsicContentSize, CGSizeZero)); XCTAssertEqual(scaleBar.alpha, 0); self.mapView.zoomLevel = 15; @@ -49,7 +49,7 @@ XCTAssertFalse(scaleBar.hidden); // Directly setting `.hidden` after the map has finished initializing will not update the scale bar. - XCTAssertTrue(CGRectIsEmpty(scaleBar.frame)); + XCTAssertTrue(CGSizeEqualToSize(scaleBar.intrinsicContentSize, CGSizeZero)); // ... but triggering any camera event will update it. self.mapView.zoomLevel = 1; |