Reputation: 13
I'm trying to measure the number of lines of a Text without rendering it. I thought I could use a TextMeasurer, however the number of "measured" lines is different than the number of lines I get if I render the actual Text.
This is the code I'm using:
Box () {
val textMeasurer = rememberTextMeasurer()
val measuredLayoutResult = textMeasurer.measure(
largeText)
println("Measured lines: ${measuredLayoutResult.lineCount}, " +
"Measured height: ${measuredLayoutResult.size.height}, " +
"Measured width: ${measuredLayoutResult.size.width}")
Text(
largeText,
onTextLayout = { textLayoutResult ->
println("Actual lines: ${textLayoutResult.lineCount}, " +
"Actual height: ${textLayoutResult.size.height}, " +
"Actual width: ${textLayoutResult.size.width}")
},
)
}
I would expect the numbers to be the same, instead I'm getting the following: Measured lines: 25, Measured height: 1132, Measured width: 30154 Actual lines: 235, Actual height: 2088, Actual width: 1080
Any ideas what I am doing wrong?
Upvotes: 1
Views: 1376
Reputation: 67248
When you don't assign constraints param to measure function of TextMeasurer it uses default Constraints
with maxWidth and maxHeight with Constraints.Infinity
.
@Stable
fun measure(
text: String,
style: TextStyle = TextStyle.Default,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
constraints: Constraints = Constraints(),
layoutDirection: LayoutDirection = this.defaultLayoutDirection,
density: Density = this.defaultDensity,
fontFamilyResolver: FontFamily.Resolver = this.defaultFontFamilyResolver,
skipCache: Boolean = false
)
Use a BoxWithConstraints
and pass a Constraints from it to limit total width that text can be measured with
@Preview
@Composable
private fun Test() {
val largeText =
"some large tatasda sdasdasdsa dasdasd asda sdasd asdasd asdasdasdasdasdasdasdasdasd"
BoxWithConstraints {
val textMeasurer = rememberTextMeasurer()
val measuredLayoutResult = textMeasurer.measure(
constraints = constraints,
text = largeText
)
println(
"Measured lines: ${measuredLayoutResult.lineCount}, " +
"Measured height: ${measuredLayoutResult.size.height}, " +
"Measured width: ${measuredLayoutResult.size.width}"
)
Text(
largeText,
onTextLayout = { textLayoutResult ->
println(
"Actual lines: ${textLayoutResult.lineCount}, " +
"Actual height: ${textLayoutResult.size.height}, " +
"Actual width: ${textLayoutResult.size.width}"
)
},
)
}
}
Upvotes: 0
Reputation: 10887
Make sure that you provide all text styling arguments that you applied to the Text Composable to the measure
function too (in case you truncated the code you posted).
If the code you posted is the exact code you have, then my guess is that the Box
with the TextMeasurer
exceeds the screen, while the Text
for some reason doesn't. According to the Box
documentation,
The
Box
will size itself to fit the content, subject to the incoming constraints.
So you could try to define the size of the Box to fit the screen and see if the issue persists:
Box (modifier = Modifier.fillMaxSize()) {
val textMeasurer = rememberTextMeasurer()
val measuredLayoutResult = textMeasurer.measure(largeText)
//...
}
Upvotes: 0