Skip to content

Commit

Permalink
[Chips] Resize MDCChipField's textField frame instead of using left i…
Browse files Browse the repository at this point in the history
…nsets to align with chips (material-components#9827)

* [Chips] Resize MDCChipField's textField frame instead of using left insets to align with chips

* Update tests to reflect text field frame editing (instead of placeholder frame editing)

* clang
  • Loading branch information
bryanoltman authored Mar 3, 2020
1 parent fff5c06 commit 04567ba
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 35 deletions.
70 changes: 44 additions & 26 deletions components/Chips/src/MDCChipField.m
Original file line number Diff line number Diff line change
Expand Up @@ -698,28 +698,60 @@ - (BOOL)isTextFieldEmpty {

- (CGRect)frameForTextFieldForLastChipFrame:(CGRect)lastChipFrame
chipFieldSize:(CGSize)chipFieldSize {
CGFloat textFieldWidth =
chipFieldSize.width - self.contentEdgeInsets.left - self.contentEdgeInsets.right;
CGFloat availableWidth = [self availableWidthForTextInput];
CGFloat textFieldHeight = [self.textField sizeThatFits:chipFieldSize].height;
CGFloat originY = lastChipFrame.origin.y + (self.chipHeight - textFieldHeight) / 2;

// If no chip exists, make the text field the full width minus padding.
// If no chip exists, make the text field the full width, adjusted for insets.
if (CGRectIsEmpty(lastChipFrame)) {
// Adjust for the top inset
originY += self.contentEdgeInsets.top;
return CGRectMake(self.contentEdgeInsets.left, originY, textFieldWidth, textFieldHeight);
return CGRectMake(self.contentEdgeInsets.left, originY, availableWidth, textFieldHeight);
}

CGFloat availableWidth = chipFieldSize.width - self.contentEdgeInsets.right -
CGRectGetMaxX(lastChipFrame) - MDCChipFieldHorizontalMargin;
CGFloat placeholderDesiredWidth = [self placeholderDesiredWidth];
if (availableWidth < placeholderDesiredWidth) {
CGFloat originX = 0;
CGFloat textFieldWidth = 0;
CGFloat desiredTextWidth = [self textInputDesiredWidth];
if (availableWidth < desiredTextWidth) {
// The text field doesn't fit on the line with the last chip.
originY += self.chipHeight + MDCChipFieldVerticalMargin;
return CGRectMake(self.contentEdgeInsets.left, originY, textFieldWidth, textFieldHeight);
originX = self.contentEdgeInsets.left;
textFieldWidth =
chipFieldSize.width - self.contentEdgeInsets.left - self.contentEdgeInsets.right;
} else {
// The text field fits on the line with chips
originX += CGRectGetMaxX(lastChipFrame) + MDCChipFieldHorizontalMargin;
textFieldWidth = availableWidth;
}

return CGRectMake(self.contentEdgeInsets.left, originY, textFieldWidth, textFieldHeight);
return CGRectMake(originX, originY, textFieldWidth, textFieldHeight);
}

- (CGFloat)availableWidthForTextInput {
NSArray *chipFrames = [self chipFramesForSize:self.bounds.size];
CGFloat boundsWidth = CGRectGetWidth(CGRectStandardize(self.bounds));
if (chipFrames.count == 0) {
return boundsWidth - (self.contentEdgeInsets.right + self.contentEdgeInsets.left);
}

CGRect lastChipFrame = [chipFrames.lastObject CGRectValue];
CGFloat availableWidth = boundsWidth - self.contentEdgeInsets.right -
CGRectGetMaxX(lastChipFrame) - MDCChipFieldHorizontalMargin;
return availableWidth;
}

// The width of the text input + the clear button.
- (CGFloat)textInputDesiredWidth {
UIFont *font = self.textField.placeholderLabel.font;
CGRect placeholderDesiredRect = [self.textField.text
boundingRectWithSize:CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{
NSFontAttributeName : font,
}
context:nil];
return MAX([self placeholderDesiredWidth],
CGRectGetWidth(placeholderDesiredRect) + MDCChipFieldHorizontalMargin +
self.contentEdgeInsets.right + MDCChipFieldClearImageSquareWidthHeight);
}

- (CGFloat)placeholderDesiredWidth {
Expand All @@ -742,21 +774,7 @@ - (CGFloat)placeholderDesiredWidth {

- (UIEdgeInsets)textInsets:(UIEdgeInsets)defaultInsets
withSizeThatFitsWidthHint:(CGFloat)widthHint {
CGRect lastChipFrame = self.chips.lastObject.frame;
if (self.mdf_effectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
lastChipFrame = MDFRectFlippedHorizontally(lastChipFrame, CGRectGetWidth(self.bounds));
}

CGFloat availableWidth = CGRectGetWidth(self.bounds) - self.contentEdgeInsets.right -
CGRectGetMaxX(lastChipFrame) - MDCChipFieldHorizontalMargin;

CGFloat leftInset = MDCChipFieldIndent;
if (!CGRectIsEmpty(lastChipFrame) && availableWidth >= [self placeholderDesiredWidth]) {
leftInset +=
CGRectGetMaxX(lastChipFrame) + MDCChipFieldHorizontalMargin - self.contentEdgeInsets.left;
}
defaultInsets.left = leftInset;

defaultInsets.left = MDCChipFieldIndent;
return defaultInsets;
}

Expand Down
14 changes: 5 additions & 9 deletions components/Chips/tests/unit/ChipsTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -323,19 +323,17 @@ - (void)testRemoveChipsManually {
// When
[field createNewChipFromInput];
[field layoutIfNeeded];
CGFloat placeholderWithChipOriginX =
CGRectStandardize(field.textField.placeholderLabel.frame).origin.x;
CGFloat placeholderWithChipOriginX = CGRectStandardize(field.textField.frame).origin.x;
MDCChipView *chip = field.chips[0];
[field removeChip:chip];
[field layoutIfNeeded];

// Then
CGFloat finalPlaceholderPositionOriginX =
CGRectStandardize(field.textField.placeholderLabel.frame).origin.x;
CGFloat finalPlaceholderPositionOriginX = CGRectStandardize(field.textField.frame).origin.x;
XCTAssertGreaterThan(placeholderWithChipOriginX, finalPlaceholderPositionOriginX);
}

- (void)testAddChipsManuallyPlaceholderCorrectPosition {
- (void)testAddChipsManuallyTextFieldCorrectPosition {
// Given
MDCChipView *fakeChip = [[MDCChipView alloc] init];
fakeChip.titleLabel.text = @"Fake chip";
Expand All @@ -346,16 +344,14 @@ - (void)testAddChipsManuallyPlaceholderCorrectPosition {
// When
[fakeField setNeedsLayout];
[fakeField layoutIfNeeded];
CGFloat initialPlaceholderOriginX =
CGRectStandardize(fakeField.textField.placeholderLabel.frame).origin.x;
CGFloat initialPlaceholderOriginX = CGRectStandardize(fakeField.textField.frame).origin.x;
[fakeField addChip:fakeChip];
fakeField.textField.placeholder = fakeField.textField.placeholder;
[fakeField setNeedsLayout];
[fakeField layoutIfNeeded];

// Then
CGFloat finalPlaceholderOriginX =
CGRectStandardize(fakeField.textField.placeholderLabel.frame).origin.x;
CGFloat finalPlaceholderOriginX = CGRectStandardize(fakeField.textField.frame).origin.x;
XCTAssertGreaterThan(finalPlaceholderOriginX, initialPlaceholderOriginX);
}

Expand Down

0 comments on commit 04567ba

Please sign in to comment.