I am working on a Jetpack Compose based app which shows a simple list with 3 columns.
Things are working in principle. What I am struggling with is how to automatically determine the size of the columns.
For example, the width requirement of the date column will differ significantly depending on the user's locale settings and font size.
24.12.2021 - 20:00
requires a lot less screen space than
12/14/2021 - 08:00 PM
.
What I was hoping I can do is to work with a sample date, measure it up based on current locale settings and font size and then set the width for all list entries accordingly.
Something similar to this:
val d = Date(2021, 12, 30, 23, 59, 59) // Sample date
val t = dateFormat.format(d) + " - " + timeFormat.format(d) // Build the output string
val dateColumnWidth = measureTextWidth(t, fontSize) // This is what I need
…
LazyColumn {
…
Row {
Text(text = t, Modifier.width(dateColumnWidth.dp), fontSize = fontSize.sp))
Text(text = value)
Text(text = comment)
}
}
…
I have been on this for weeks but a function like my "measureTextWidth" above doesn't seem to exist.
Is there any way to achieve this?
You can use SubcomposeLayout
like this:
@Composable
fun MeasureUnconstrainedViewWidth(
viewToMeasure: @Composable () -> Unit,
content: @Composable (measuredWidth: Dp) -> Unit,
) {
SubcomposeLayout { constraints ->
val measuredWidth = subcompose("viewToMeasure", viewToMeasure)[0]
.measure(Constraints()).width.toDp()
val contentPlaceable = subcompose("content") {
content(measuredWidth)
}[0].measure(constraints)
layout(contentPlaceable.width, contentPlaceable.height) {
contentPlaceable.place(0, 0)
}
}
}
Then use it in your view:
MeasureUnconstrainedViewWidth(
viewToMeasure = {
Text("your sample text")
}
) { measuredWidth ->
// use measuredWidth to create your view
}
If all you want is a measureTextWidth
function that measures the width of a given text according to a given TextStyle, here's the function:
@Composable
fun measureTextWidth(text: String, style: TextStyle): Dp {
val textMeasurer = rememberTextMeasurer()
val widthInPixels = textMeasurer.measure(text, style).size.width
return with(LocalDensity.current) { widthInPixels.toDp() }
}
This function is inspired by Xam's answer here in a different thread.
Here is an example of how you would use this function:
val textStyle = TextStyle(fontSize = 16.sp)
val text = "12/14/2021 - 08:00 PM"
val dateColumnWidth = measureTextWidth(text, textStyle)
Row {
Text(text = dateTime, Modifier.width(dateColumnWidth), style = textStyle)
Text(text = value, style = textStyle)
Text(text = comment, style = textStyle)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With