Skip to content

Commit

Permalink
Port over constraint-based support for multiline button from MDCButton.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 590209948
  • Loading branch information
Wenyu Zhang authored and material-automation committed Dec 12, 2023
1 parent 976983f commit 37976f7
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 0 deletions.
16 changes: 16 additions & 0 deletions components/M3CButton/src/M3CButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,22 @@ __attribute__((objc_subclassing_restricted))
*/
@property(nonatomic) NSTimeInterval animationDuration;

#pragma mark - Enabling multi-line layout

/**
When enabled, makes use of constraints to enable the title label to wrap to multiple lines.
Note: this property does not currently support buttons with images. Enabling this property when an
image is present will result in undefined behavior. On iOS 15+, please consider using @c
UIButtonConfiguration for multiline button.
Precondition: use this property to enable multiline button only under auto layout. Use @c
textCanWrap under manual layout.
Default value is @c NO.
*/
@property(nonatomic) BOOL layoutTitleWithConstraints;

/**
Should the button's label be rendered on multiple lines. If you set this
property to YES, make sure that your button has either its
Expand Down
57 changes: 57 additions & 0 deletions components/M3CButton/src/M3CButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ @interface M3CButton () {
BOOL _customInsetAvailable;
}

// Used only when layoutTitleWithConstraints is enabled.
@property(nonatomic, strong, nullable) NSLayoutConstraint *titleTopConstraint;
@property(nonatomic, strong, nullable) NSLayoutConstraint *titleBottomConstraint;
@property(nonatomic, strong, nullable) NSLayoutConstraint *titleLeadingConstraint;
@property(nonatomic, strong, nullable) NSLayoutConstraint *titleTrailingConstraint;

@end

@implementation M3CButton
Expand Down Expand Up @@ -208,6 +214,11 @@ - (void)setEdgeInsetsWithTitleOnly:(UIEdgeInsets)edgeInsetsWithTitleOnly {
- (void)setContentEdgeInsets:(UIEdgeInsets)edgeInsets {
[super setContentEdgeInsets:edgeInsets];
_customInsetAvailable = YES;

// Update constraint constants for multiline layout.
if (self.layoutTitleWithConstraints) {
[self updateTitleLabelConstraint];
}
}

- (void)updateInsets {
Expand Down Expand Up @@ -310,6 +321,52 @@ - (CGSize)clampToMinimumSize:(CGSize)size {
size.width = MAX(MAX(size.height, size.width), _minimumWidth);
return size;
}
#pragma mark - Enabling multi-line layout

- (void)setLayoutTitleWithConstraints:(BOOL)layoutTitleWithConstraints {
if (_layoutTitleWithConstraints == layoutTitleWithConstraints) {
return;
}

_layoutTitleWithConstraints = layoutTitleWithConstraints;

if (_layoutTitleWithConstraints) {
self.titleTopConstraint = [self.titleLabel.topAnchor constraintEqualToAnchor:self.topAnchor];
self.titleBottomConstraint =
[self.titleLabel.bottomAnchor constraintEqualToAnchor:self.bottomAnchor];
self.titleLeadingConstraint =
[self.titleLabel.leadingAnchor constraintEqualToAnchor:self.leadingAnchor];
self.titleTrailingConstraint =
[self.titleLabel.trailingAnchor constraintEqualToAnchor:self.trailingAnchor];
self.titleTopConstraint.active = YES;
self.titleBottomConstraint.active = YES;
self.titleLeadingConstraint.active = YES;
self.titleTrailingConstraint.active = YES;

[self.titleLabel setContentHuggingPriority:UILayoutPriorityRequired
forAxis:UILayoutConstraintAxisHorizontal];
[self.titleLabel setContentHuggingPriority:UILayoutPriorityRequired
forAxis:UILayoutConstraintAxisVertical];

[self updateTitleLabelConstraint];
} else {
self.titleTopConstraint.active = NO;
self.titleBottomConstraint.active = NO;
self.titleLeadingConstraint.active = NO;
self.titleTrailingConstraint.active = NO;
self.titleTopConstraint = nil;
self.titleBottomConstraint = nil;
self.titleLeadingConstraint = nil;
self.titleTrailingConstraint = nil;
}
}

- (void)updateTitleLabelConstraint {
self.titleTopConstraint.constant = self.contentEdgeInsets.top;
self.titleBottomConstraint.constant = -self.contentEdgeInsets.bottom;
self.titleLeadingConstraint.constant = self.contentEdgeInsets.left;
self.titleTrailingConstraint.constant = -self.contentEdgeInsets.right;
}

- (CGSize)sizeBasedOnLabel {
CGFloat textWidth = self.titleLabel.preferredMaxLayoutWidth;
Expand Down

0 comments on commit 37976f7

Please sign in to comment.