summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Guerra Soto <fabian.guerra@mapbox.com>2018-01-10 14:28:55 -0600
committerGitHub <noreply@github.com>2018-01-10 14:28:55 -0600
commit0542ece0bf2456db3ca7f0140bb6ac43c4697a97 (patch)
treecbc281b9d139ada533bae743612359209b524097
parenta3c497f100b488802aba7c04b2096e0617271cdf (diff)
downloadqtlocation-mapboxgl-0542ece0bf2456db3ca7f0140bb6ac43c4697a97.tar.gz
[ios] Fix the layout constraints on iOS 11 for iPhone X (#10858)
* [ios] Fix the layout constraints on iOS 11 for iPhone X for the bottom ornaments. * WIP adding tests for layout of map view attribution logo and other ornaments * Rename * First pass at tests for mapview ornament layout * Additional code changes from call with Fabian and Jason * [ios] Fix ornaments insets margin space. * [ios] Fix map view layout test for pre iOS 11. * [ios] Refactor MGLMapView ornaments layout constraints for iOS 11. * [ios] Remove NSLogs from MGLMapViewLayoutTests
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj4
-rw-r--r--platform/ios/src/MGLMapView.mm56
-rw-r--r--platform/ios/test/MGLMapViewLayoutTests.m108
3 files changed, 136 insertions, 32 deletions
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index c405e92d35..52f33a83b6 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -12,6 +12,7 @@
071BBB031EE76146001FB02A /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
071BBB041EE76147001FB02A /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
071BBB071EE77631001FB02A /* MGLImageSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */; };
+ 16376B491FFEED010000563E /* MGLMapViewLayoutTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */; };
1753ED421E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -580,6 +581,7 @@
071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLImageSource.h; sourceTree = "<group>"; };
071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLImageSource.mm; sourceTree = "<group>"; };
071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLImageSourceTests.m; path = ../../darwin/test/MGLImageSourceTests.m; sourceTree = "<group>"; };
+ 16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLMapViewLayoutTests.m; sourceTree = "<group>"; };
1753ED411E53CE6F00A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
1F0666881EC64F8E001C16D7 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
1F0666891EC64F8E001C16D7 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
@@ -1365,6 +1367,7 @@
DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */,
DA2E885C1CC0382C00F24E7B /* MGLGeometryTests.mm */,
DA5DB1291FABF1EE001C2326 /* MGLMapAccessibilityElementTests.m */,
+ 16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */,
35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */,
1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */,
DAE7DEC11E245455007505A6 /* MGLNSStringAdditionsTests.m */,
@@ -2311,6 +2314,7 @@
DA0CD5901CF56F6A00A5F5A5 /* MGLFeatureTests.mm in Sources */,
556660D81E1D085500E2C41B /* MGLVersionNumber.m in Sources */,
4031ACFF1E9FD29F00A3EA26 /* MGLSDKTestHelpers.swift in Sources */,
+ 16376B491FFEED010000563E /* MGLMapViewLayoutTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index c02446609a..0849cbd12f 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -753,7 +753,7 @@ public:
toItem:viewController.topLayoutGuide
attribute:NSLayoutAttributeBottom
multiplier:1.0
- constant:5.0]];
+ constant:8.0]];
}
[self.compassViewConstraints addObject:
[NSLayoutConstraint constraintWithItem:self.compassView
@@ -762,7 +762,7 @@ public:
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1.0
- constant:5.0 + self.contentInset.top]];
+ constant:8.0 + self.contentInset.top]];
[self.compassViewConstraints addObject:
[NSLayoutConstraint constraintWithItem:self
@@ -771,7 +771,7 @@ public:
toItem:self.compassView
attribute:NSLayoutAttributeTrailing
multiplier:1.0
- constant:5.0 + self.contentInset.right]];
+ constant:8.0 + self.contentInset.right]];
[containerView addConstraints:self.compassViewConstraints];
@@ -788,7 +788,7 @@ public:
toItem:viewController.topLayoutGuide
attribute:NSLayoutAttributeBottom
multiplier:1.0
- constant:5.0]];
+ constant:8.0]];
}
[self.scaleBarConstraints addObject:
[NSLayoutConstraint constraintWithItem:self.scaleBar
@@ -797,7 +797,7 @@ public:
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1.0
- constant:5.0 + self.contentInset.top]];
+ constant:8.0 + self.contentInset.top]];
[self.scaleBarConstraints addObject:
[NSLayoutConstraint constraintWithItem:self.scaleBar
attribute:NSLayoutAttributeLeft
@@ -831,7 +831,7 @@ public:
toItem:self.logoView
attribute:NSLayoutAttributeBaseline
multiplier:1
- constant:8 + self.contentInset.bottom]];
+ constant:8.0 + self.contentInset.bottom]];
[self.logoViewConstraints addObject:
[NSLayoutConstraint constraintWithItem:self.logoView
attribute:NSLayoutAttributeLeading
@@ -855,7 +855,7 @@ public:
toItem:self.attributionButton
attribute:NSLayoutAttributeBaseline
multiplier:1
- constant:8 + self.contentInset.bottom]];
+ constant:8.0 + self.contentInset.bottom]];
}
[self.attributionButtonConstraints addObject:
[NSLayoutConstraint constraintWithItem:self
@@ -864,7 +864,7 @@ public:
toItem:self.attributionButton
attribute:NSLayoutAttributeBaseline
multiplier:1
- constant:8 + self.contentInset.bottom]];
+ constant:8.0 + self.contentInset.bottom]];
[self.attributionButtonConstraints addObject:
[NSLayoutConstraint constraintWithItem:self
@@ -873,29 +873,20 @@ public:
toItem:self.attributionButton
attribute:NSLayoutAttributeTrailing
multiplier:1
- constant:8 + self.contentInset.right]];
+ constant:8.0 + self.contentInset.right]];
[containerView addConstraints:self.attributionButtonConstraints];
}
- (void)updateConstraints
{
-
-// If compiling with the iOS 11+ SDK
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
// If safeAreaLayoutGuide API exists
- if ( [self respondsToSelector:@selector(safeAreaLayoutGuide)] ) {
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpartial-availability"
+ if (@available(iOS 11.0, *)) {
UILayoutGuide *safeAreaLayoutGuide = self.safeAreaLayoutGuide;
-#pragma clang diagnostic pop
+
// compass view
[self removeConstraints:self.compassViewConstraints];
[self.compassViewConstraints removeAllObjects];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpartial-availability"
- [self.compassViewConstraints addObject:[self.compassView.topAnchor constraintEqualToSystemSpacingBelowAnchor:safeAreaLayoutGuide.topAnchor multiplier:1]];
-#pragma clang diagnostic pop
+ [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];
@@ -903,10 +894,7 @@ public:
// scale bar view
[self removeConstraints:self.scaleBarConstraints];
[self.scaleBarConstraints removeAllObjects];
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpartial-availability"
- [self.scaleBarConstraints addObject:[self.scaleBar.topAnchor constraintEqualToSystemSpacingBelowAnchor:safeAreaLayoutGuide.topAnchor multiplier:1]];
-#pragma clang diagnostic pop
+ [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];
@@ -914,8 +902,7 @@ public:
// logo view
[self removeConstraints:self.logoViewConstraints];
[self.logoViewConstraints removeAllObjects];
- [self.logoViewConstraints addObject:[safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:self.logoView.bottomAnchor
- constant:8.0 + self.contentInset.bottom]];
+ [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];
@@ -923,21 +910,26 @@ public:
// attribution button
[self removeConstraints:self.attributionButtonConstraints];
[self.attributionButtonConstraints removeAllObjects];
- [self.attributionButtonConstraints addObject:[safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:self.attributionButton.bottomAnchor
- constant:8.0 + self.contentInset.bottom]];
+ [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];
}
-#else
- [self updateConstraintsPreiOS11];
-#endif
[super updateConstraints];
}
+- (NSLayoutConstraint *)constraintForYAxisAnchor:(NSLayoutYAxisAnchor *)yAxisAnchor belowAnchor:(NSLayoutYAxisAnchor *)anchor
+{
+ if (@available(iOS 11.0, *)) {
+ return [yAxisAnchor constraintEqualToSystemSpacingBelowAnchor:anchor multiplier:1];
+ } else {
+ return nil;
+ }
+}
+
- (BOOL)isOpaque
{
return _opaque;
diff --git a/platform/ios/test/MGLMapViewLayoutTests.m b/platform/ios/test/MGLMapViewLayoutTests.m
new file mode 100644
index 0000000000..a41e7695f9
--- /dev/null
+++ b/platform/ios/test/MGLMapViewLayoutTests.m
@@ -0,0 +1,108 @@
+#import <XCTest/XCTest.h>
+#import "MGLMapView.h"
+#import "MGLMapViewDelegate.h"
+#import "MGLAccountManager.h"
+
+
+@interface MGLMapViewLayoutTests : XCTestCase<MGLMapViewDelegate>
+
+@property (nonatomic) UIView *superView;
+@property (nonatomic) MGLMapView *mapView;
+@property (nonatomic) XCTestExpectation *styleLoadingExpectation;
+
+@end
+
+@implementation MGLMapViewLayoutTests
+
+- (void)setUp {
+ [super setUp];
+
+ [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+
+ self.superView = [[UIView alloc] initWithFrame:UIScreen.mainScreen.bounds];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:UIScreen.mainScreen.bounds styleURL:styleURL];
+ self.mapView.delegate = self;
+
+ [self.superView addSubview:self.mapView];
+
+ UIView *mapView = self.mapView;
+ NSDictionary *bindings = NSDictionaryOfVariableBindings(mapView);
+ NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[mapView]-0-|" options:0 metrics:nil views:bindings];
+ NSArray *horizonatalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[mapView]-0-|" options:0 metrics:nil views:bindings];
+
+ [self.superView addConstraints:[verticalConstraints arrayByAddingObjectsFromArray:horizonatalConstraints]];
+
+ self.styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
+ [self waitForExpectationsWithTimeout:1 handler:nil];
+
+ //set zoom and heading so that scale bar and compass will be shown
+ [self.mapView setZoomLevel:4.5 animated:NO];
+ [self.mapView.camera setHeading:12.0];
+
+ //invoke layout
+ [self.superView setNeedsLayout];
+ [self.superView layoutIfNeeded];
+
+}
+
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ XCTAssertNotNil(mapView.style);
+ XCTAssertEqual(mapView.style, style);
+
+ [self.styleLoadingExpectation fulfill];
+}
+
+- (void)tearDown {
+ self.styleLoadingExpectation = nil;
+ self.mapView = nil;
+
+ [super tearDown];
+}
+
+- (void)testOrnamentPlacement {
+
+ CGFloat margin = 8.0;
+ CGFloat bottomSafeAreaInset = 0.0;
+ double accuracy = 0.01;
+
+ if ( [self.mapView respondsToSelector:@selector(safeAreaInsets)] ) {
+ bottomSafeAreaInset = self.mapView.safeAreaInsets.bottom;
+ }
+
+ //compass
+ UIImageView *compassView = self.mapView.compassView;
+
+ CGFloat expectedCompassOriginX = CGRectGetMaxX(self.mapView.bounds) - margin - CGRectGetWidth(compassView.frame);
+ CGFloat expectedCompassOriginY = margin;
+
+ XCTAssertEqualWithAccuracy(CGRectGetMinX(compassView.frame), expectedCompassOriginX, accuracy);
+ XCTAssertEqualWithAccuracy(CGRectGetMinY(compassView.frame), expectedCompassOriginY, accuracy);
+
+ //scale bar
+ UIView *scaleBar = self.mapView.scaleBar;
+
+ XCTAssertEqualWithAccuracy(CGRectGetMinX(scaleBar.frame), margin, accuracy);
+ XCTAssertEqualWithAccuracy(CGRectGetMinY(scaleBar.frame), margin, accuracy);
+
+ //attribution button
+ UIButton *attributionButton = self.mapView.attributionButton;
+
+ CGFloat expectedButtonOriginX = CGRectGetMaxX(self.mapView.bounds) - margin - CGRectGetWidth(attributionButton.frame);
+ CGFloat expectedButtonOriginY = CGRectGetMaxY(self.mapView.bounds) - margin - bottomSafeAreaInset - CGRectGetHeight(attributionButton.frame);
+
+ XCTAssertEqualWithAccuracy(CGRectGetMinX(attributionButton.frame), expectedButtonOriginX, accuracy);
+ XCTAssertEqualWithAccuracy(CGRectGetMinY(attributionButton.frame), expectedButtonOriginY, accuracy);
+
+ //mapbox logo
+ UIImageView *logoView = self.mapView.logoView;
+
+ CGFloat expectedLogoOriginX = margin;
+ CGFloat expectedLogoOriginY = CGRectGetMaxY(self.mapView.bounds) - margin - bottomSafeAreaInset - CGRectGetHeight(logoView.frame);
+
+ XCTAssertEqualWithAccuracy(CGRectGetMinX(logoView.frame), expectedLogoOriginX, accuracy);
+ XCTAssertEqualWithAccuracy(CGRectGetMinY(logoView.frame), expectedLogoOriginY, accuracy);
+}
+
+@end