Skip to content

Commit

Permalink
[BottomSheet] Add property so clients can set a custom height for bot…
Browse files Browse the repository at this point in the history
…tom sheet (#5139)

Previously clients could only set a custom height for bottom sheet by setting the `preferredContentSize` this adds a property so clients can set a specific height and not touch `preferredContentSize`.

Related to #4945
  • Loading branch information
codeman7 committed Sep 18, 2018
1 parent faea5d1 commit 553fb01
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 15 deletions.
12 changes: 12 additions & 0 deletions components/BottomSheet/src/MDCBottomSheetPresentationController.h
Expand Up @@ -64,6 +64,18 @@
*/
@property(nonatomic, assign) BOOL dismissOnBackgroundTap;

/**
This is used to set a custom height on the sheet view.
@note If a positive value is passed then the sheet view will be that height even if
perferredContentSize has been set. Otherwise the sheet will open up to half the screen height or
the size of the presentedViewController's preferredContentSize whatever value is smaller.
@note The preferredSheetHeight can never be taller than the height of the content, if the content
is smaller than the value passed to preferredSheetHeight then the sheet view will be the size of
the content height.
*/
@property(nonatomic, assign) CGFloat preferredSheetHeight;

/**
If @c YES, then the dimmed scrim view will act as an accessibility element for dismissing the
bottom sheet.
Expand Down
22 changes: 16 additions & 6 deletions components/BottomSheet/src/MDCBottomSheetPresentationController.m
Expand Up @@ -108,7 +108,7 @@ - (void)presentationTransitionWillBegin {
[containerView addSubview:_dimmingView];
[containerView addSubview:self.sheetView];

[self setPreferredSheetHeight:self.presentedViewController.preferredContentSize.height];
[self updatePreferredSheetHeight];

// Add tap handler to dismiss the sheet.
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self
Expand Down Expand Up @@ -155,7 +155,7 @@ - (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentConta
[super preferredContentSizeDidChangeForChildContentContainer:container];
self.sheetView.frame = [self frameOfPresentedViewInContainerView];
[self.sheetView layoutIfNeeded];
[self setPreferredSheetHeight:self.presentedViewController.preferredContentSize.height];
[self updatePreferredSheetHeight];
}

- (void)viewWillTransitionToSize:(CGSize)size
Expand All @@ -167,7 +167,7 @@ - (void)viewWillTransitionToSize:(CGSize)size
__unused id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
self.sheetView.frame = [self frameOfPresentedViewInContainerView];
[self.sheetView layoutIfNeeded];
[self setPreferredSheetHeight:self.presentedViewController.preferredContentSize.height];
[self updatePreferredSheetHeight];
}
completion:nil];
}
Expand All @@ -176,11 +176,16 @@ - (void)viewWillTransitionToSize:(CGSize)size
Sets the new value of @c sheetView.preferredSheetHeight.
If @c preferredContentHeight is non-positive, it will set it to half of sheetView's
frame's height.
@param preferredSheetHeight If positive, the new value for @sheetView.preferredSheetHeight.
*/
- (void)setPreferredSheetHeight:(CGFloat)preferredSheetHeight {
- (void)updatePreferredSheetHeight {
// If |preferredSheetHeight| has not been specified, use half of the current height.
CGFloat preferredSheetHeight;
if (self.preferredSheetHeight > 0.f) {
preferredSheetHeight = self.preferredSheetHeight;
} else {
preferredSheetHeight = self.presentedViewController.preferredContentSize.height;
}

if (MDCCGFloatEqual(preferredSheetHeight, 0)) {
preferredSheetHeight = MDCRound(CGRectGetHeight(self.sheetView.frame) / 2);
}
Expand Down Expand Up @@ -244,6 +249,11 @@ - (UIAccessibilityTraits)scrimAccessibilityTraits {
return _scrimAccessibilityTraits;
}

- (void)setPreferredSheetHeight:(CGFloat)preferredSheetHeight {
_preferredSheetHeight = preferredSheetHeight;
[self updatePreferredSheetHeight];
}

#pragma mark - MDCSheetContainerViewDelegate

- (void)sheetContainerViewDidHide:(nonnull __unused MDCSheetContainerView *)containerView {
Expand Down
13 changes: 13 additions & 0 deletions components/BottomSheet/src/MDCBottomSheetTransitionController.h
Expand Up @@ -45,6 +45,19 @@
*/
@property(nonatomic, assign) BOOL dismissOnBackgroundTap;

/**
This is used to set a custom height on the sheet view. This is can be used to set the initial
height when the ViewController is presented.
@note If a positive value is passed then the sheet view will be that height even if
perferredContentSize has been set. Otherwise the sheet will open up to half the screen height or
the size of the presentedViewController's preferredContentSize whatever value is smaller.
@note The preferredSheetHeight can never be taller than the height of the content, if the content
is smaller than the value passed to preferredSheetHeight then the sheet view will be the size of
the content height.
*/
@property(nonatomic, assign) CGFloat preferredSheetHeight;

@end

@interface MDCBottomSheetTransitionController (ScrimAccessibility)
Expand Down
Expand Up @@ -48,6 +48,7 @@ - (instancetype)init {
presentationController.isScrimAccessibilityElement = _isScrimAccessibilityElement;
presentationController.scrimAccessibilityHint = _scrimAccessibilityHint;
presentationController.scrimAccessibilityLabel = _scrimAccessibilityLabel;
presentationController.preferredSheetHeight = _preferredSheetHeight;
return presentationController;
}

Expand Down
Expand Up @@ -22,7 +22,7 @@
// Exposing internal methods for unit testing
@interface MDCBottomSheetPresentationController (Testing)
@property(nonatomic, strong) MDCSheetContainerView *sheetView;
- (void)setPreferredSheetHeight:(CGFloat)preferredSheetHeight;
- (void)updatePreferredSheetHeight;
@end

/**
Expand Down Expand Up @@ -79,53 +79,150 @@ - (void)setUp {
self.presentationController.sheetView = self.sheetView;
}

- (void)testSetPreferredSheetHeightZeroWhenSheetViewHasStandardizedFrame {
- (void)testUpdatePreferredSheetHeightZeroWhenSheetViewHasStandardizedFrame {
// Given
CGFloat sheetFrameHeight = 80;
self.sheetView.frame = CGRectMake(0, 0, 75, sheetFrameHeight);

// When
[self.presentationController setPreferredSheetHeight:0];
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(self.sheetView.preferredSheetHeight, sheetFrameHeight / 2, 0.001);
}

- (void)testSetPreferredSheetHeightZeroWhenSheetViewHasUnstandardizedFrame {
- (void)testUpdatePreferredSheetHeightZeroWhenSheetViewHasUnstandardizedFrame {
// Given
CGFloat sheetFrameHeight = -80;
self.sheetView.frame = CGRectMake(75, 80, -75, sheetFrameHeight);

// When
[self.presentationController setPreferredSheetHeight:0];
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(self.sheetView.preferredSheetHeight,
(CGFloat)fabs(sheetFrameHeight / 2), 0.001);
}

- (void)testSetPreferredSheetHeightPositiveValue {
- (void)testUpdatePreferredSheetHeightPositiveValue {
// Given
CGFloat preferredSheetHeight = 120;
self.presentationController.presentedViewController.preferredContentSize =
CGSizeMake(100, preferredSheetHeight);
self.sheetView.frame = CGRectMake(0, 0, 75, 80);

// When
[self.presentationController setPreferredSheetHeight:preferredSheetHeight];
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(self.sheetView.preferredSheetHeight, preferredSheetHeight, 0.001);
}

- (void)testSetPreferredSheetHeightNegativeValue {
- (void)testUpdatePreferredSheetHeightNegativeValue {
// Given
CGFloat preferredSheetHeight = -120;
self.presentationController.presentedViewController.preferredContentSize =
CGSizeMake(0, preferredSheetHeight);
self.sheetView.frame = CGRectMake(0, 0, 75, -80);

// When
[self.presentationController setPreferredSheetHeight:preferredSheetHeight];
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(self.sheetView.preferredSheetHeight, preferredSheetHeight, 0.001);
}

- (void)testUpdatePreferredSheetHeight {
// Given
CGFloat preferredSheetHeight = 100;
self.presentationController.preferredSheetHeight = preferredSheetHeight;

// When
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(self.sheetView.preferredSheetHeight, preferredSheetHeight, 0.001);
}

- (void)testUpdateNegativePreferredSheetHeight {
// Given
CGFloat preferrredSheetHeight = -100;
self.presentationController.preferredSheetHeight = preferrredSheetHeight;
CGFloat sheetHeight = 250;
self.sheetView.frame = CGRectMake(0, 0, 75, sheetHeight);

// When
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(self.sheetView.preferredSheetHeight, (CGFloat)(sheetHeight / 2),
0.001);
}

- (void)testUpdatePreferredSheetHeightAndPreferredContentSize {
// Given
CGSize preferredContentSize = CGSizeMake(100, 100);
CGFloat preferredSheetHeight = 200;
self.presentationController.presentedViewController.preferredContentSize = preferredContentSize;
self.presentationController.preferredSheetHeight = preferredSheetHeight;

// When
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(self.sheetView.preferredSheetHeight, preferredSheetHeight, 0.001);
}

- (void)testPreferredSheetHeightNegativeAndPreferredContentSizePositive {
// Given
CGSize preferredContentSize = CGSizeMake(100, 100);
CGFloat preferredSheetHeight = -200;
self.presentationController.presentedViewController.preferredContentSize = preferredContentSize;
self.presentationController.preferredSheetHeight = preferredSheetHeight;

// When
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(self.sheetView.preferredSheetHeight, preferredContentSize.height,
0.001);
}

- (void)testPreferredSheetHeightNonZeroThenZero {
// Given
CGFloat preferredSheetHeight = 200;
self.presentationController.preferredSheetHeight = preferredSheetHeight;
CGFloat sheetHeight = 300;
self.sheetView.frame = CGRectMake(0, 0, 200, sheetHeight);

// When
[self.presentationController updatePreferredSheetHeight];
self.presentationController.preferredSheetHeight = 0;
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(self.sheetView.preferredSheetHeight, (CGFloat)(sheetHeight / 2),
0.001);
}

- (void)testVeryLargePreferredSheetHeightAndSmallContent {
// Given
CGFloat scrollViewHeight = 100;
CGRect smallFrame = CGRectMake(0, 0, 200, scrollViewHeight);
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:smallFrame];
FakeSheetView *sheetView =
[[FakeSheetView alloc] initWithFrame:smallFrame
contentView:[[UIView alloc] initWithFrame:smallFrame]
scrollView:scrollView];

self.presentationController.sheetView = sheetView;
self.presentationController.preferredSheetHeight = 5000;

// When
[self.presentationController updatePreferredSheetHeight];

// Then
XCTAssertEqualWithAccuracy(CGRectGetHeight(sheetView.frame), CGRectGetHeight(smallFrame), 0.001);
}

@end

0 comments on commit 553fb01

Please sign in to comment.