Skip to content

Commit 77cdaa8

Browse files
j-piaseckifacebook-github-bot
authored andcommitted
Remove the workaround used for measuring multiline text on iOS (facebook#50028)
Summary: Pull Request resolved: facebook#50028 Changelog: [IOS][CHANGED] - Replace a workaround for measuring multiline text with `maximumNumberOfLines` on iOS with a proper solution ## Summary: In facebook#49549 support for `numberOfLines` was added to iOS `TextInput`. Along that, a workaround for measuring multiline text with limited number of lines was added to avoid an edge case coming from `NSTextContainer` measuring empty lines even if they are over the line limit. This PR handles that case properly by counting and measuring individual lines to properly handle the offending edge case. Reviewed By: NickGerleman Differential Revision: D71111841 fbshipit-source-id: 6adb4450a13fcc845604622ea76576658a7537aa
1 parent fc7385c commit 77cdaa8

File tree

1 file changed

+23
-14
lines changed
  • packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager

1 file changed

+23
-14
lines changed

packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,11 @@ - (TextMeasurement)measureNSAttributedString:(NSAttributedString *)attributedStr
4747
}
4848

4949
CGSize maximumSize = CGSize{layoutConstraints.maximumSize.width, CGFLOAT_MAX};
50-
51-
// A workaround for the issue with empty line measurement:
52-
// When maximumNumberOfLines is set to N and N+1 line is empty, the returned
53-
// measurement is for N+1 lines. Adding any character to that line results
54-
// in the correct measurement.
55-
if (paragraphAttributes.maximumNumberOfLines > 0 && attributedString.length > 0 &&
56-
[[attributedString string] characterAtIndex:attributedString.length - 1] == '\n') {
57-
NSMutableAttributedString *mutableString =
58-
[[NSMutableAttributedString alloc] initWithAttributedString:attributedString];
59-
[mutableString replaceCharactersInRange:NSMakeRange(attributedString.length - 1, 1) withString:@"\n "];
60-
attributedString = mutableString;
61-
}
62-
6350
NSTextStorage *textStorage = [self _textStorageAndLayoutManagerWithAttributesString:attributedString
6451
paragraphAttributes:paragraphAttributes
6552
size:maximumSize];
6653

67-
return [self _measureTextStorage:textStorage];
54+
return [self _measureTextStorage:textStorage paragraphAttributes:paragraphAttributes];
6855
}
6956

7057
- (TextMeasurement)measureAttributedString:(AttributedString)attributedString
@@ -341,13 +328,16 @@ - (NSAttributedString *)_nsAttributedStringFromAttributedString:(AttributedStrin
341328
}
342329

343330
- (TextMeasurement)_measureTextStorage:(NSTextStorage *)textStorage
331+
paragraphAttributes:(ParagraphAttributes)paragraphAttributes
344332
{
345333
NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject;
346334
NSTextContainer *textContainer = layoutManager.textContainers.firstObject;
347335
[layoutManager ensureLayoutForTextContainer:textContainer];
348336

349337
NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer];
350338
__block BOOL textDidWrap = NO;
339+
__block NSUInteger linesEnumerated = 0;
340+
__block CGFloat enumeratedLinesHeight = 0;
351341
[layoutManager
352342
enumerateLineFragmentsForGlyphRange:glyphRange
353343
usingBlock:^(
@@ -363,6 +353,13 @@ - (TextMeasurement)_measureTextStorage:(NSTextStorage *)textStorage
363353
[textStorage.string characterAtIndex:lastCharacterIndex] == '\n';
364354
if (!endsWithNewLine && textStorage.string.length > lastCharacterIndex + 1) {
365355
textDidWrap = YES;
356+
}
357+
if (linesEnumerated++ < paragraphAttributes.maximumNumberOfLines) {
358+
enumeratedLinesHeight = usedRect.origin.y + usedRect.size.height;
359+
}
360+
if (textDidWrap &&
361+
(paragraphAttributes.maximumNumberOfLines == 0 ||
362+
linesEnumerated >= paragraphAttributes.maximumNumberOfLines)) {
366363
*stop = YES;
367364
}
368365
}];
@@ -373,6 +370,18 @@ - (TextMeasurement)_measureTextStorage:(NSTextStorage *)textStorage
373370
size.width = textContainer.size.width;
374371
}
375372

373+
if (paragraphAttributes.maximumNumberOfLines != 0) {
374+
// If maximumNumberOfLines is set, we cannot rely on setting it on the NSTextContainer
375+
// due to an edge case where it returns wrong height:
376+
// When maximumNumberOfLines is set to N and the N+1 line is empty, the measured height
377+
// is N+1 lines (incorrect). Adding any characted to the N+1 line, making it non-empty
378+
// casuses the measured height to be N lines (correct).
379+
if (linesEnumerated < paragraphAttributes.maximumNumberOfLines) {
380+
enumeratedLinesHeight += layoutManager.extraLineFragmentUsedRect.size.height;
381+
}
382+
size.height = enumeratedLinesHeight;
383+
}
384+
376385
size = (CGSize){RCTCeilPixelValue(size.width), RCTCeilPixelValue(size.height)};
377386

378387
__block auto attachments = TextMeasurement::Attachments{};

0 commit comments

Comments
 (0)