Skip to content

Commit 92d50d4

Browse files
bernhardojkelset
authored andcommitted
Resubmit D46501420 (#37790)
Summary: Multiline text in Android shows some extra space. It's easily noticeable when you set the text `alignSelf` to `flex-start`. This is because we are using `layout.getLineWidth` which will include trailing whitespace. <img width="300" alt="image" src="https://github.com/facebook/react-native/assets/50919443/8939092b-caef-4ad8-9b34-2ccef5d20968"> Based on Android doc, `getLineMax` exclude trailing whitespace. <img width="625" alt="image" src="https://github.com/facebook/react-native/assets/50919443/0b32e842-5fab-4fc7-8fd9-299877b9c553"> ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID] [FIXED] - Exclude trailing whitespace from newline character on measuring text line width For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [ANDROID] [FIXED] - Exclude trailing whitespace from newline character on measuring text line width Pull Request resolved: #37790 Test Plan: After applying the changes: <img width="300" alt="image" src="https://github.com/facebook/react-native/assets/50919443/bfbf52b0-7e7d-4c89-8958-6af38d8bc1c7"> Code snippet: ``` <Text style={{backgroundColor: 'red', alignSelf: 'flex-start', color: 'white'}}> 1{'\n'} </Text> ``` Reviewed By: cortinico Differential Revision: D46586516 Pulled By: NickGerleman fbshipit-source-id: 3ea9c150ad92082f9b4d1da453ba0ef04b09ce51
1 parent 4ddfeb6 commit 92d50d4

File tree

5 files changed

+27
-7
lines changed

5 files changed

+27
-7
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/FontMetricsUtil.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@ public static WritableArray getFontMetrics(
4242
X_HEIGHT_MEASUREMENT_TEXT, 0, X_HEIGHT_MEASUREMENT_TEXT.length(), xHeightBounds);
4343
double xHeight = xHeightBounds.height() / AMPLIFICATION_FACTOR / dm.density;
4444
for (int i = 0; i < layout.getLineCount(); i++) {
45+
boolean endsWithNewLine = text.length() > 0 && text.charAt(layout.getLineEnd(i) - 1) == '\n';
46+
float lineWidth = endsWithNewLine ? layout.getLineMax(i) : layout.getLineWidth(i);
4547
Rect bounds = new Rect();
4648
layout.getLineBounds(i, bounds);
4749
WritableMap line = Arguments.createMap();
4850
line.putDouble("x", layout.getLineLeft(i) / dm.density);
4951
line.putDouble("y", bounds.top / dm.density);
50-
line.putDouble("width", layout.getLineWidth(i) / dm.density);
52+
line.putDouble("width", lineWidth / dm.density);
5153
line.putDouble("height", bounds.height() / dm.density);
5254
line.putDouble("descender", layout.getLineDescent(i) / dm.density);
5355
line.putDouble("ascender", -layout.getLineAscent(i) / dm.density);

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,10 @@ public long measure(
135135
layoutWidth = width;
136136
} else {
137137
for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
138-
float lineWidth = layout.getLineWidth(lineIndex);
138+
boolean endsWithNewLine =
139+
text.length() > 0 && text.charAt(layout.getLineEnd(lineIndex) - 1) == '\n';
140+
float lineWidth =
141+
endsWithNewLine ? layout.getLineMax(lineIndex) : layout.getLineWidth(lineIndex);
139142
if (lineWidth > layoutWidth) {
140143
layoutWidth = lineWidth;
141144
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,14 @@ protected void onLayout(
264264
// the last offset in the layout will result in an endless loop. Work around
265265
// this bug by avoiding getPrimaryHorizontal in that case.
266266
if (start == text.length() - 1) {
267+
boolean endsWithNewLine =
268+
text.length() > 0 && text.charAt(layout.getLineEnd(line) - 1) == '\n';
269+
float lineWidth = endsWithNewLine ? layout.getLineMax(line) : layout.getLineWidth(line);
267270
placeholderHorizontalPosition =
268271
isRtlParagraph
269272
// Equivalent to `layout.getLineLeft(line)` but `getLineLeft` returns incorrect
270273
// values when the paragraph is RTL and `setSingleLine(true)`.
271-
? textViewWidth - (int) layout.getLineWidth(line)
274+
? textViewWidth - (int) lineWidth
272275
: (int) layout.getLineRight(line) - width;
273276
} else {
274277
// The direction of the paragraph may not be exactly the direction the string is heading

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,10 @@ public static long measureText(
397397
calculatedWidth = width;
398398
} else {
399399
for (int lineIndex = 0; lineIndex < calculatedLineCount; lineIndex++) {
400-
float lineWidth = layout.getLineWidth(lineIndex);
400+
boolean endsWithNewLine =
401+
text.length() > 0 && text.charAt(layout.getLineEnd(lineIndex) - 1) == '\n';
402+
float lineWidth =
403+
endsWithNewLine ? layout.getLineMax(lineIndex) : layout.getLineWidth(lineIndex);
401404
if (lineWidth > calculatedWidth) {
402405
calculatedWidth = lineWidth;
403406
}
@@ -452,11 +455,14 @@ public static long measureText(
452455
// the last offset in the layout will result in an endless loop. Work around
453456
// this bug by avoiding getPrimaryHorizontal in that case.
454457
if (start == text.length() - 1) {
458+
boolean endsWithNewLine =
459+
text.length() > 0 && text.charAt(layout.getLineEnd(line) - 1) == '\n';
460+
float lineWidth = endsWithNewLine ? layout.getLineMax(line) : layout.getLineWidth(line);
455461
placeholderLeftPosition =
456462
isRtlParagraph
457463
// Equivalent to `layout.getLineLeft(line)` but `getLineLeft` returns incorrect
458464
// values when the paragraph is RTL and `setSingleLine(true)`.
459-
? calculatedWidth - layout.getLineWidth(line)
465+
? calculatedWidth - lineWidth
460466
: layout.getLineRight(line) - placeholderWidth;
461467
} else {
462468
// The direction of the paragraph may not be exactly the direction the string is heading

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,10 @@ public static long measureText(
411411
calculatedWidth = width;
412412
} else {
413413
for (int lineIndex = 0; lineIndex < calculatedLineCount; lineIndex++) {
414-
float lineWidth = layout.getLineWidth(lineIndex);
414+
boolean endsWithNewLine =
415+
text.length() > 0 && text.charAt(layout.getLineEnd(lineIndex) - 1) == '\n';
416+
float lineWidth =
417+
endsWithNewLine ? layout.getLineMax(lineIndex) : layout.getLineWidth(lineIndex);
415418
if (lineWidth > calculatedWidth) {
416419
calculatedWidth = lineWidth;
417420
}
@@ -466,12 +469,15 @@ public static long measureText(
466469
// the last offset in the layout will result in an endless loop. Work around
467470
// this bug by avoiding getPrimaryHorizontal in that case.
468471
if (start == text.length() - 1) {
472+
boolean endsWithNewLine =
473+
text.length() > 0 && text.charAt(layout.getLineEnd(line) - 1) == '\n';
474+
float lineWidth = endsWithNewLine ? layout.getLineMax(line) : layout.getLineWidth(line);
469475
placeholderLeftPosition =
470476
isRtlParagraph
471477
// Equivalent to `layout.getLineLeft(line)` but `getLineLeft` returns
472478
// incorrect
473479
// values when the paragraph is RTL and `setSingleLine(true)`.
474-
? calculatedWidth - layout.getLineWidth(line)
480+
? calculatedWidth - lineWidth
475481
: layout.getLineRight(line) - placeholderWidth;
476482
} else {
477483
// The direction of the paragraph may not be exactly the direction the string is

0 commit comments

Comments
 (0)