[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:
committed by
GitHub
parent
a3c497f100
commit
0542ece0bf
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
108
platform/ios/test/MGLMapViewLayoutTests.m
Normal file
108
platform/ios/test/MGLMapViewLayoutTests.m
Normal 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
|
||||
Reference in New Issue
Block a user