[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
This commit is contained in:
Fabian Guerra Soto
2018-01-10 14:28:55 -06:00
committed by GitHub
parent a3c497f100
commit 0542ece0bf
3 changed files with 136 additions and 32 deletions

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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