-
Notifications
You must be signed in to change notification settings - Fork 24.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TextLayout: take full width if text wrapped #47435
Conversation
cc @cipolleschi or @realsoelynn You may want to review this since you have the context from #41770 |
@realsoelynn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
That also likely fixes issue reported here. facebook/yoga#1730 I think we may want this behavior regardless of max number of lines. Wrapping when we have AtMost constraint should be changed on iOS/Android to take full available width. |
@realsoelynn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
@NickGerleman It won't fix the other issue. That one is in yoga. I will look into it as well |
@realsoelynn I see a failing internal test. Does this require any action from my side? |
@s77rt @realsoelynn the other issue was reported to Yoga, but I highly suspect it is RN measure function issue related to what this change is addressing. |
Making this a draft, will work on what @NickGerleman suggested. It should fix both this issue and the other one |
Ready for review. cc @realsoelynn @NickGerleman |
FYI: @NickGerleman is on PTO this week. He should be back next week |
@realsoelynn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Back from PTO! Took a look, and I think we might need to handle max-content differently.
if (!endsWithNewLine && lineIndex + 1 < layout.getLineCount()) { | ||
calculatedWidth = width; | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we may also reach this path when widthYogaMeasureMode
is YogaMeasureMode.UNDEFINED
, in which case we are asking for max-content size, and the width
is NaN
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think on L604, we could replace:
if (widthYogaMeasureMode == YogaMeasureMode.AT_MOST && calculatedWidth > width)
with
if (widthYogaMeasureMode == YogaMeasureMode.AT_MOST && (calculatedWidth > width || layout.getLineCount() > 1))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we may also reach this path when widthYogaMeasureMode is YogaMeasureMode.UNDEFINED
In this case, should we keep the calculated width as the max width of the lines?
I think on L604, we could replace
We set calculatedWidth = width only if the text wraps due to overflow. If the user write 2 short lines we still use the width of the maximum line
CGSize size = [layoutManager usedRectForTextContainer:textContainer].size; | ||
|
||
if (textDidWrap) { | ||
size.width = textContainer.size.width; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we may have similar case to the above, for measuring max-content, where we don't want to set to size. I think in this case, it looks like that might be represented as Infinity
layout constraint which makes its way to the NSTextContainer
.
NSUInteger lastCharacterIndex = range.location + range.length - 1; | ||
BOOL endsWithNewLine = | ||
[textStorage.string characterAtIndex:lastCharacterIndex] == '\n'; | ||
if (!endsWithNewLine && textStorage.string.length > lastCharacterIndex + 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this correctly detect wrapping for something like the below?
Hello\n
World\n
I think we may be able to just count lines. https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextLayout/Tasks/CountLines.html#//apple_ref/doc/uid/20001810-CJBGBIBB
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, that's not considered text wrap. In this case we want the current behaviour (text width) otherwise we'd break case 2 from #47435 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you are correct about only wanting to do this when we need to break due to wrapping.
That also solves the max-content case, since we will never wrap in this case since we have unconstrained width.
So I think this is good!
@realsoelynn has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
This pull request was successfully merged by @s77rt in 550b0c0 When will my fix make it into a release? | How to file a pick request? |
@realsoelynn merged this pull request in 550b0c0. |
Summary:
Problem
The calculated width for a multiline text is based on the longest line. However it does not account for text that wraps.
Example if numberOfLines=1 and the text wraps
The TextView will render
because the
calculatedWidth
took the width of the first line.Also see #41770 (comment) for additional context.
Solution
If the text wraps, take the whole width.
Fixes #39722
Fixes facebook/yoga#1730
Changelog:
[GENERAL] [FIXED] - Fix text not taking full width
Test Plan: