Skip to content

Commit

Permalink
Refactor out the layout calculations for title, title icon, message a…
Browse files Browse the repository at this point in the history
…nd the view insets into private methods.

This allows to avoid code duplication and enables easier update of the layout to GM2 design.

PiperOrigin-RevId: 292035417
  • Loading branch information
iberezan authored and Jeff Verkoeyen committed Jan 29, 2020
1 parent 4083596 commit b092209
Showing 1 changed file with 89 additions and 77 deletions.
166 changes: 89 additions & 77 deletions components/Dialogs/src/private/MDCAlertControllerView+Private.m
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,77 @@ - (CGSize)actionButtonsSizeInVerticalLayout {
return size;
}

- (BOOL)hasTitleIcon {
return (0.0f < self.titleIconImageView.image.size.height);
}

- (BOOL)hasTitle {
return self.title.length > 0;
}

- (BOOL)hasMessage {
return self.message.length > 0;
}

- (CGFloat)contentInternalVerticalPadding {
return (([self hasTitle] || [self hasTitleIcon]) && [self hasMessage])
? MDCDialogContentVerticalPadding
: 0.0f;
}

- (CGFloat)contentTitleIconVerticalPadding {
return ([self hasTitle] && [self hasTitleIcon]) ? MDCDialogTitleIconVerticalPadding : 0.0f;
}

- (CGFloat)contentAccessoryVerticalPaddingWithFittingSize:(CGSize)boundsSize {
CGSize accessoryViewSize = [self.accessoryView systemLayoutSizeFittingSize:boundsSize];
return (([self hasTitle] || [self hasTitleIcon] || [self hasMessage]) &&
(0.0 < accessoryViewSize.height))
? MDCDialogContentVerticalPadding
: 0.0f;
}

- (CGSize)titleIconSize {
return (self.titleIconImageView != nil) ? self.titleIconImageView.image.size : CGSizeZero;
}

- (CGFloat)titleTop {
return MDCDialogContentInsets.top + [self contentTitleIconVerticalPadding] +
[self titleIconSize].height;
}

- (CGRect)titleFrameWithTitleSize:(CGSize)titleSize {
return CGRectMake(MDCDialogContentInsets.left, [self titleTop], titleSize.width,
titleSize.height);
}

- (CGRect)messageFrameWithTitleSize:(CGSize)titleSize messageSize:(CGSize)messageSize {
CGRect messageFrame = CGRectMake(MDCDialogContentInsets.left,
CGRectGetMaxY([self titleFrameWithTitleSize:titleSize]) +
[self contentInternalVerticalPadding],
messageSize.width, messageSize.height);
return messageFrame;
}

- (CGRect)titleIconFrameWithTitleSize:(CGSize)titleSize {
CGSize titleIconSize = [self titleIconSize];
CGRect titleFrame = [self titleFrameWithTitleSize:titleSize];
// match the titleIcon alignment to the title alignment
CGFloat titleIconLeftPadding = MDCDialogContentInsets.left;
if (self.titleAlignment == NSTextAlignmentCenter) {
titleIconLeftPadding =
CGRectGetMinX(titleFrame) + (CGRectGetWidth(titleFrame) - titleIconSize.width) / 2;
} else if (self.titleAlignment == NSTextAlignmentRight ||
(self.titleAlignment == NSTextAlignmentNatural &&
[self mdf_effectiveUserInterfaceLayoutDirection] ==
UIUserInterfaceLayoutDirectionRightToLeft)) {
titleIconLeftPadding = CGRectGetMaxX(titleFrame) - titleIconSize.width;
}
CGRect titleIconFrame = CGRectMake(titleIconLeftPadding, MDCDialogContentInsets.top,
titleIconSize.width, titleIconSize.height);
return titleIconFrame;
}

// @param boundsSize should not include any internal margins or padding
- (CGSize)calculatePreferredContentSizeForBounds:(CGSize)boundsSize {
// Even if we have more room, limit our maximum width
Expand All @@ -411,40 +482,20 @@ - (CGSize)calculateContentSizeThatFitsWidth:(CGFloat)boundingWidth {
CGSize boundsSize = CGRectInfinite.size;
boundsSize.width = boundingWidth - MDCDialogContentInsets.left - MDCDialogContentInsets.right;

CGSize titleIconSize = CGSizeZero;
if (self.titleIconImageView != nil) {
// TODO(galiak): Have title-icon size respond to dynamic type or device screen size, once this:
// https://github.com/material-components/material-components-ios/issues/5198 is resolved.
titleIconSize = self.titleIconImageView.image.size;
}
BOOL hasTitleIcon = (0.0 < titleIconSize.height);

CGSize titleSize = [self.titleLabel sizeThatFits:boundsSize];
BOOL hasTitle = (0.0 < titleSize.height);
CGSize messageSize = [self.messageLabel sizeThatFits:boundsSize];
BOOL hasMessage = (0.0 < messageSize.height);
CGSize accessoryViewSize = [self.accessoryView systemLayoutSizeFittingSize:boundsSize];
BOOL hasAccessory = (0.0 < accessoryViewSize.height);
CGFloat contentAccessoryVerticalPadding =
[self contentAccessoryVerticalPaddingWithFittingSize:boundsSize];

CGFloat contentWidth = MAX(MAX(titleSize.width, messageSize.width), accessoryViewSize.width);
contentWidth += MDCDialogContentInsets.left + MDCDialogContentInsets.right;
CGFloat contentWidth = MAX(MAX(titleSize.width, messageSize.width), accessoryViewSize.width) +
MDCDialogContentInsets.left + MDCDialogContentInsets.right;

CGFloat contentInternalVerticalPadding = 0.0;
if ((hasTitle || hasTitleIcon) && hasMessage) {
contentInternalVerticalPadding = MDCDialogContentVerticalPadding;
}
CGFloat contentTitleIconVerticalPadding = 0.0;
if (hasTitle && hasTitleIcon) {
contentTitleIconVerticalPadding = MDCDialogTitleIconVerticalPadding;
}
CGFloat contentAccessoryVerticalPadding = 0.0;
if ((hasTitle || hasTitleIcon || hasMessage) && hasAccessory) {
contentAccessoryVerticalPadding = MDCDialogContentVerticalPadding;
}
CGFloat contentHeight = titleIconSize.height + contentTitleIconVerticalPadding +
titleSize.height + contentInternalVerticalPadding + messageSize.height +
contentAccessoryVerticalPadding + accessoryViewSize.height;
contentHeight += MDCDialogContentInsets.top + MDCDialogContentInsets.bottom;
CGFloat contentHeight = MDCDialogContentInsets.top + [self titleIconSize].height +
[self contentTitleIconVerticalPadding] + titleSize.height +
[self contentInternalVerticalPadding] + messageSize.height +
contentAccessoryVerticalPadding + accessoryViewSize.height +
MDCDialogContentInsets.bottom;

CGSize contentSize;
contentSize.width = (CGFloat)ceil(contentWidth);
Expand Down Expand Up @@ -516,74 +567,35 @@ - (void)layoutSubviews {
boundsSize.width = boundsSize.width - MDCDialogContentInsets.left - MDCDialogContentInsets.right;
CGSize titleSize = [self.titleLabel sizeThatFits:boundsSize];
titleSize.width = boundsSize.width;
BOOL hasTitle = (0.0 < titleSize.height);

CGSize titleIconSize = CGSizeZero;
if (self.titleIconImageView != nil) {
// TODO(galiak): Have title-icon size respond to dynamic type or device screen size, once this:
// https://github.com/material-components/material-components-ios/issues/5198 is resolved.
titleIconSize = self.titleIconImageView.image.size;
}
BOOL hasTitleIcon = (0.0 < titleIconSize.height);

CGSize messageSize = [self.messageLabel sizeThatFits:boundsSize];
messageSize.width = boundsSize.width;
BOOL hasMessage = (0.0 < messageSize.height);

CGSize accessoryViewSize =
[self.accessoryView systemLayoutSizeFittingSize:boundsSize
withHorizontalFittingPriority:UILayoutPriorityRequired
verticalFittingPriority:UILayoutPriorityFittingSizeLevel];
accessoryViewSize.width = boundsSize.width;
BOOL hasAccessory = (0.0 < accessoryViewSize.height);

boundsSize.width = boundsSize.width + MDCDialogContentInsets.left + MDCDialogContentInsets.right;

CGFloat contentInternalVerticalPadding = 0.0;
if ((hasTitle || hasTitleIcon) && hasMessage) {
contentInternalVerticalPadding = MDCDialogContentVerticalPadding;
}
CGFloat contentTitleIconVerticalPadding = 0.0;
if (hasTitle && hasTitleIcon) {
contentTitleIconVerticalPadding = MDCDialogTitleIconVerticalPadding;
}
CGFloat contentAccessoryVerticalPadding = 0.0;
if ((hasTitle || hasTitleIcon || hasMessage) && hasAccessory) {
contentAccessoryVerticalPadding = MDCDialogContentVerticalPadding;
}

CGFloat titleTop =
MDCDialogContentInsets.top + contentTitleIconVerticalPadding + titleIconSize.height;
CGRect titleFrame =
CGRectMake(MDCDialogContentInsets.left, titleTop, titleSize.width, titleSize.height);
CGRect messageFrame = CGRectMake(MDCDialogContentInsets.left,
CGRectGetMaxY(titleFrame) + contentInternalVerticalPadding,
messageSize.width, messageSize.height);
CGFloat contentAccessoryVerticalPadding =
[self contentAccessoryVerticalPaddingWithFittingSize:boundsSize];
CGRect titleFrame = [self titleFrameWithTitleSize:titleSize];
CGRect messageFrame = [self messageFrameWithTitleSize:titleSize messageSize:messageSize];
CGRect accessoryViewFrame = CGRectMake(
MDCDialogContentInsets.left, CGRectGetMaxY(messageFrame) + contentAccessoryVerticalPadding,
accessoryViewSize.width, accessoryViewSize.height);

if (self.titleIconImageView != nil) {
// Match the title icon alignment to the title alignment.
self.titleIconImageView.frame = [self titleIconFrameWithTitleSize:titleSize];
}

self.titleLabel.frame = titleFrame;
self.messageLabel.frame = messageFrame;
self.accessoryView.frame = accessoryViewFrame;

if (self.titleIconImageView != nil) {
// Match the titleIcon alignment to the title alignment.
CGFloat titleIconPosition = titleFrame.origin.x;
if (self.titleAlignment == NSTextAlignmentCenter) {
titleIconPosition =
CGRectGetMinX(titleFrame) + (CGRectGetWidth(titleFrame) - titleIconSize.width) / 2;
} else if (self.titleAlignment == NSTextAlignmentRight ||
(self.titleAlignment == NSTextAlignmentNatural &&
[self mdf_effectiveUserInterfaceLayoutDirection] ==
UIUserInterfaceLayoutDirectionRightToLeft)) {
titleIconPosition = CGRectGetMaxX(titleFrame) - titleIconSize.width;
}
CGRect titleIconFrame = CGRectMake(titleIconPosition, MDCDialogContentInsets.top,
titleIconSize.width, titleIconSize.height);
self.titleIconImageView.frame = titleIconFrame;
}

// Actions
CGSize actionSize = [self calculateActionsSizeThatFitsWidth:boundsSize.width];

Expand Down

0 comments on commit b092209

Please sign in to comment.