Skip to content
Permalink
Browse files

[NavigationDrawer] Include safe area insets in content height (#7545)

This adds a new opt-in flag for clients to tell the drawer to add the bottom safe area inset to the content height. That way the content can be seen correctly without overlapping on the bottom safe area.

This issue has been reported by an internal client and helps with bug: b/123500336 .

This is a follow up PR to #7544
  • Loading branch information
yarneo committed Jun 6, 2019
1 parent bff2914 commit 37fbe0ba48f7df106ab50f1167a34feba3fd9b60
@@ -101,6 +101,14 @@
*/
@property(nonatomic, assign) CGFloat maximumInitialDrawerHeight;

/**
A flag allowing clients to opt-in to the drawer adding additional height to the content to include
the bottom safe area inset. This will remove the need for clients to calculate their content size
with the bottom safe area when setting the preferredContentSize of the contentViewController.
Defaults to NO.
*/
@property(nonatomic, assign) BOOL shouldIncludeSafeAreaInContentHeight;

/**
A boolean value that indicates whether the drawer is currently the full height of the window.
*/
@@ -76,6 +76,8 @@ - (void)presentationTransitionWillBegin {
bottomDrawerContainerViewController.maximumInitialDrawerHeight =
self.maximumInitialDrawerHeight;
}
bottomDrawerContainerViewController.shouldIncludeSafeAreaInContentHeight =
self.shouldIncludeSafeAreaInContentHeight;
if ([self.presentedViewController isKindOfClass:[MDCBottomDrawerViewController class]]) {
// If in fact the presentedViewController is an MDCBottomDrawerViewController,
// we then know there is a content and an (optional) header view controller.
@@ -82,6 +82,14 @@
*/
@property(nonatomic, assign) CGFloat maximumInitialDrawerHeight;

/**
A flag allowing clients to opt-in to the drawer adding additional height to the content to include
the bottom safe area inset. This will remove the need for clients to calculate their content size
with the bottom safe area when setting the preferredContentSize of the contentViewController.
Defaults to NO.
*/
@property(nonatomic, assign) BOOL shouldIncludeSafeAreaInContentHeight;

/**
The bottom drawer delegate.
*/
@@ -176,6 +176,16 @@ - (void)setMaximumInitialDrawerHeight:(CGFloat)maximumInitialDrawerHeight {
}
}

- (void)setShouldIncludeSafeAreaInContentHeight:(BOOL)shouldIncludeSafeAreaInContentHeight {
_shouldIncludeSafeAreaInContentHeight = shouldIncludeSafeAreaInContentHeight;
if ([self.presentationController isKindOfClass:[MDCBottomDrawerPresentationController class]]) {
MDCBottomDrawerPresentationController *bottomDrawerPresentationController =
(MDCBottomDrawerPresentationController *)self.presentationController;
bottomDrawerPresentationController.shouldIncludeSafeAreaInContentHeight =
shouldIncludeSafeAreaInContentHeight;
}
}

#pragma mark UIAccessibilityAction

// Adds the Z gesture for dismissal.
@@ -130,6 +130,14 @@
*/
@property(nonatomic, assign) CGFloat maximumInitialDrawerHeight;

/**
A flag allowing clients to opt-in to the drawer adding additional height to the content to include
the bottom safe area inset. This will remove the need for clients to calculate their content size
with the bottom safe area when setting the preferredContentSize of the contentViewController.
Defaults to NO.
*/
@property(nonatomic, assign) BOOL shouldIncludeSafeAreaInContentHeight;

/**
Sets the content offset Y of the drawer's content. If contentOffsetY is set to 0, the
drawer will scroll to the start of its content.
@@ -515,7 +515,8 @@ - (CGFloat)calculateMaximumInitialDrawerHeight {
_contentVCPreferredContentSizeHeightCached;
const CGFloat maximumInitialHeight = _maximumInitialDrawerHeight;
if (totalHeight > maximumInitialHeight ||
MDCCGFloatEqual(_contentVCPreferredContentSizeHeightCached, 0)) {
MDCCGFloatEqual(_contentVCPreferredContentSizeHeightCached,
[self bottomSafeAreaInsetsToAdjustContainerHeight])) {
// Have the drawer height stay its current size in cases where the content preferred content
// size is still not updated, or when the content height and header height are bigger than the
// initial height.
@@ -524,6 +525,15 @@ - (CGFloat)calculateMaximumInitialDrawerHeight {
return totalHeight;
}

- (CGFloat)bottomSafeAreaInsetsToAdjustContainerHeight {
if (@available(iOS 11.0, *)) {
if (self.shouldIncludeSafeAreaInContentHeight) {
return self.view.safeAreaInsets.bottom;
}
}
return 0;
}

#pragma mark Set ups (Private)

- (void)setUpContentHeader {
@@ -740,7 +750,8 @@ - (void)cacheLayoutCalculations {
- (void)cacheLayoutCalculationsWithAddedContentHeight:(CGFloat)addedContentHeight {
CGFloat contentHeaderHeight = self.contentHeaderHeight;
CGFloat containerHeight = self.presentingViewBounds.size.height;
CGFloat contentHeight = self.contentViewController.preferredContentSize.height;
CGFloat contentHeight = self.contentViewController.preferredContentSize.height +
[self bottomSafeAreaInsetsToAdjustContainerHeight];
if ([self shouldPresentFullScreen]) {
contentHeight = MAX(contentHeight, containerHeight - self.topHeaderHeight);
}
@@ -736,4 +736,19 @@ - (void)testMaximumInitialDrawerHeightWhenPreferredContentSizeIsntUpdatedYet {
XCTAssertEqualWithAccuracy(drawerHeight, 250, 0.001);
}

- (void)testSettingShouldIncludeSafeAreaInContentHeight {
// Given
self.drawerViewController.shouldIncludeSafeAreaInContentHeight = YES;

// When
MDCBottomDrawerPresentationController *presentationController =
(MDCBottomDrawerPresentationController *)self.drawerViewController.presentationController;
[presentationController presentationTransitionWillBegin];

// Then
XCTAssertTrue(presentationController.shouldIncludeSafeAreaInContentHeight);
XCTAssertTrue(presentationController.bottomDrawerContainerViewController
.shouldIncludeSafeAreaInContentHeight);
}

@end

0 comments on commit 37fbe0b

Please sign in to comment.
You can’t perform that action at this time.