mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Remove the workaround used for measuring multiline text on iOS (#50028)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50028 Changelog: [IOS][CHANGED] - Replace a workaround for measuring multiline text with `maximumNumberOfLines` on iOS with a proper solution ## Summary: In https://github.com/facebook/react-native/pull/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
This commit is contained in:
committed by
Facebook GitHub Bot
parent
fc7385c1ea
commit
77cdaa8733
+23
-14
@@ -47,24 +47,11 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
|
||||
}
|
||||
|
||||
CGSize maximumSize = CGSize{layoutConstraints.maximumSize.width, CGFLOAT_MAX};
|
||||
|
||||
// A workaround for the issue with empty line measurement:
|
||||
// When maximumNumberOfLines is set to N and N+1 line is empty, the returned
|
||||
// measurement is for N+1 lines. Adding any character to that line results
|
||||
// in the correct measurement.
|
||||
if (paragraphAttributes.maximumNumberOfLines > 0 && attributedString.length > 0 &&
|
||||
[[attributedString string] characterAtIndex:attributedString.length - 1] == '\n') {
|
||||
NSMutableAttributedString *mutableString =
|
||||
[[NSMutableAttributedString alloc] initWithAttributedString:attributedString];
|
||||
[mutableString replaceCharactersInRange:NSMakeRange(attributedString.length - 1, 1) withString:@"\n "];
|
||||
attributedString = mutableString;
|
||||
}
|
||||
|
||||
NSTextStorage *textStorage = [self _textStorageAndLayoutManagerWithAttributesString:attributedString
|
||||
paragraphAttributes:paragraphAttributes
|
||||
size:maximumSize];
|
||||
|
||||
return [self _measureTextStorage:textStorage];
|
||||
return [self _measureTextStorage:textStorage paragraphAttributes:paragraphAttributes];
|
||||
}
|
||||
|
||||
- (TextMeasurement)measureAttributedString:(AttributedString)attributedString
|
||||
@@ -341,6 +328,7 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
|
||||
}
|
||||
|
||||
- (TextMeasurement)_measureTextStorage:(NSTextStorage *)textStorage
|
||||
paragraphAttributes:(ParagraphAttributes)paragraphAttributes
|
||||
{
|
||||
NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject;
|
||||
NSTextContainer *textContainer = layoutManager.textContainers.firstObject;
|
||||
@@ -348,6 +336,8 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
|
||||
|
||||
NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer];
|
||||
__block BOOL textDidWrap = NO;
|
||||
__block NSUInteger linesEnumerated = 0;
|
||||
__block CGFloat enumeratedLinesHeight = 0;
|
||||
[layoutManager
|
||||
enumerateLineFragmentsForGlyphRange:glyphRange
|
||||
usingBlock:^(
|
||||
@@ -363,6 +353,13 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
|
||||
[textStorage.string characterAtIndex:lastCharacterIndex] == '\n';
|
||||
if (!endsWithNewLine && textStorage.string.length > lastCharacterIndex + 1) {
|
||||
textDidWrap = YES;
|
||||
}
|
||||
if (linesEnumerated++ < paragraphAttributes.maximumNumberOfLines) {
|
||||
enumeratedLinesHeight = usedRect.origin.y + usedRect.size.height;
|
||||
}
|
||||
if (textDidWrap &&
|
||||
(paragraphAttributes.maximumNumberOfLines == 0 ||
|
||||
linesEnumerated >= paragraphAttributes.maximumNumberOfLines)) {
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
@@ -373,6 +370,18 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
|
||||
size.width = textContainer.size.width;
|
||||
}
|
||||
|
||||
if (paragraphAttributes.maximumNumberOfLines != 0) {
|
||||
// If maximumNumberOfLines is set, we cannot rely on setting it on the NSTextContainer
|
||||
// due to an edge case where it returns wrong height:
|
||||
// When maximumNumberOfLines is set to N and the N+1 line is empty, the measured height
|
||||
// is N+1 lines (incorrect). Adding any characted to the N+1 line, making it non-empty
|
||||
// casuses the measured height to be N lines (correct).
|
||||
if (linesEnumerated < paragraphAttributes.maximumNumberOfLines) {
|
||||
enumeratedLinesHeight += layoutManager.extraLineFragmentUsedRect.size.height;
|
||||
}
|
||||
size.height = enumeratedLinesHeight;
|
||||
}
|
||||
|
||||
size = (CGSize){RCTCeilPixelValue(size.width), RCTCeilPixelValue(size.height)};
|
||||
|
||||
__block auto attachments = TextMeasurement::Attachments{};
|
||||
|
||||
Reference in New Issue
Block a user