Skip to content

Commit 8c2f2d8

Browse files
Daniel Famakinfacebook-github-bot
authored andcommitted
do truncation inline with main layout
Summary: Reviewing a new batch of screenshots after D54698703 showed some more flaws in how we're truncating. The initial height of the text layout is derived from the layout object https://www.internalfb.com/code/fbsource/[05747540c982b8816899085a43b5ec9160d12f08]/fbandroid/libraries/rendercore/rendercore-text/src/main/java/com/facebook/rendercore/text/TextMeasurementUtils.java?lines=295 But the layout logic can add and remove some spacing from the initial height in the following scenarios: https://www.internalfb.com/code/fbsource/[05747540c982b8816899085a43b5ec9160d12f08]/fbandroid/libraries/rendercore/rendercore-text/src/main/java/com/facebook/rendercore/text/TextMeasurementUtils.java?lines=297-298%2C300-302 https://www.internalfb.com/code/fbsource/[05747540c982b8816899085a43b5ec9160d12f08]/fbandroid/libraries/rendercore/rendercore-text/src/main/java/com/facebook/rendercore/text/TextMeasurementUtils.java?lines=319-325 This eventually results in the final reported height being different from the actual layout's height. In our current approach to truncation, we compare the reported (modified) height against the initial text layout's height and then go ahead to truncate which is not really correct. What we should do is truncate the initial layout against the height constraints in the measure spec and then go on to modify the spacing as needed. This should be more correct. ---- I expect most (if not all) of the failing tests to start passing after this lands. This is the last change to the logic (hopefully) Reviewed By: rooju Differential Revision: D54874150 fbshipit-source-id: 1b6028e8836cc20faf5b059718654d5985eccc91
1 parent 4380d0a commit 8c2f2d8

File tree

1 file changed

+31
-48
lines changed

1 file changed

+31
-48
lines changed

litho-rendercore-text/src/main/java/com/facebook/rendercore/text/TextMeasurementUtils.java

Lines changed: 31 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -92,21 +92,6 @@ public static MountableLayoutResult layout(
9292
}
9393

9494
Pair<Rect, TextLayout> result = layout(androidContext, widthSpec, heightSpec, text, textStyle);
95-
final boolean fitTextToConstraints =
96-
textStyle.shouldTruncateTextUsingConstraints
97-
&& textStyle.maxLines == Integer.MAX_VALUE
98-
&& View.MeasureSpec.getMode(heightSpec) != View.MeasureSpec.UNSPECIFIED;
99-
if (fitTextToConstraints) {
100-
final int measuredHeightConstraint = result.first.height();
101-
final boolean isSizeCompatible =
102-
LayoutMeasureUtil.getHeight(result.second.layout) <= measuredHeightConstraint;
103-
if (!isSizeCompatible) {
104-
result =
105-
maybeFitTextToConstraints(
106-
androidContext, heightSpec, widthSpec, textStyle, text, result);
107-
}
108-
}
109-
11095
if (textStyle.roundedBackgroundProps != null && text instanceof Spannable) {
11196
result =
11297
calculateLayoutWithBackgroundSpan(
@@ -117,39 +102,6 @@ public static MountableLayoutResult layout(
117102
renderUnit, result.first.width(), result.first.height(), result.second);
118103
}
119104

120-
private static Pair<Rect, TextLayout> maybeFitTextToConstraints(
121-
Context context,
122-
int heightSpec,
123-
int widthSpec,
124-
TextStyle textStyle,
125-
CharSequence text,
126-
Pair<Rect, TextLayout> initialResult) {
127-
final Layout layout = initialResult.second.layout;
128-
129-
final int measuredHeightConstraint = initialResult.first.height();
130-
131-
// Make sure we have the bare minimum line count if we've exhausted all lines and weren't able
132-
// to fit. This allows to show the ellipsis in the best case scenario signaling truncation
133-
int linesWithinConstrainedBounds = 1;
134-
int lineIndex = layout.getLineCount() - 1;
135-
while (lineIndex >= 0) {
136-
if (layout.getLineBottom(lineIndex) <= measuredHeightConstraint) {
137-
linesWithinConstrainedBounds = lineIndex + 1;
138-
break;
139-
}
140-
141-
lineIndex -= 1;
142-
}
143-
144-
if (layout.getLineCount() > linesWithinConstrainedBounds) {
145-
textStyle.setMaxLines(linesWithinConstrainedBounds);
146-
textStyle.setEllipsize(TextUtils.TruncateAt.END);
147-
return layout(context, widthSpec, heightSpec, text, textStyle);
148-
}
149-
150-
return initialResult;
151-
}
152-
153105
public static Pair<Rect, TextLayout> calculateLayoutWithBackgroundSpan(
154106
final Context context,
155107
final Pair<Rect, TextLayout> result,
@@ -259,6 +211,37 @@ public static Pair<Rect, TextLayout> layout(
259211
TextMeasurementUtils.createTextLayout(
260212
context, textStyle, widthSpec, heightSpec, processedText);
261213

214+
// check if the layout should truncate based on the size constraints
215+
int linesWithinConstrainedBounds = -1;
216+
if (View.MeasureSpec.getMode(heightSpec) != View.MeasureSpec.UNSPECIFIED) {
217+
final int heightConstraint = View.MeasureSpec.getSize(heightSpec);
218+
final boolean fitTextToConstraints =
219+
textStyle.shouldTruncateTextUsingConstraints
220+
&& textStyle.maxLines == Integer.MAX_VALUE
221+
&& LayoutMeasureUtil.getHeight(layout) > heightConstraint;
222+
223+
if (fitTextToConstraints) {
224+
linesWithinConstrainedBounds = 1;
225+
int lineIndex = layout.getLineCount() - 1;
226+
while (lineIndex >= 0) {
227+
if (layout.getLineBottom(lineIndex) <= heightConstraint) {
228+
linesWithinConstrainedBounds = lineIndex + 1;
229+
break;
230+
}
231+
232+
lineIndex -= 1;
233+
}
234+
}
235+
}
236+
237+
if (linesWithinConstrainedBounds != -1) {
238+
// we have constrained the number of lines that can fit, so truncate the layout
239+
textStyle.setMaxLines(linesWithinConstrainedBounds);
240+
layout =
241+
TextMeasurementUtils.createTextLayout(
242+
context, textStyle, widthSpec, heightSpec, processedText);
243+
}
244+
262245
final int layoutWidth =
263246
View.resolveSize(
264247
layout.getWidth()

0 commit comments

Comments
 (0)