Reputation: 4427
I have a layout with two texts, one on left side and one on right side. If both texts are long, left one should occupy 60%, and right one 40% of the width. But if right text is shorter than 40%, the left one should take all the available space.
Here are the examples:
and:
So I would like to write something like this:
Row {
Text(text = left, modifier = modifier.padding(8.dp).weight(<min 0.6f>))
Text(text = right, modifier = modifier.padding(8.dp).weight(<max 0.4f>))
}
Is there any way to achieve this?
Upvotes: 4
Views: 1615
Reputation: 4427
Finally, I figured it out. Here is the modifier:
fun Modifier.maxWidth(
fraction: Float = 1f,
) = layout { measurable, constraints ->
val maxWidth = (constraints.maxWidth * fraction).roundToInt()
val width = measurable.maxIntrinsicWidth(constraints.maxHeight).coerceAtMost(maxWidth)
val placeable = measurable.measure(Constraints(constraints.minWidth, width, constraints.minHeight, constraints.maxHeight))
layout(width, placeable.height) {
placeable.placeRelative(0, 0)
}
}
So we can use it like this:
Row {
Text(text = left, modifier = modifier.padding(8.dp).weight(1f)) // left text uses all the available space
Text(text = right, modifier = modifier.padding(8.dp).maxWidth(fraction = 0.4f)) // right text can be 40% of the parent or less
}
Upvotes: 8
Reputation: 29885
Measure the length of each string and calculate their weights. Adjust the weights based on the maximum allowed for the right column:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startActivity(intent)
val paint = android.graphics.Paint()
// First row
val text1 = "This long text should take up maximum 60% of the space with wrapping"
val text2 = "This is not very long"
val width1 = paint.measureText(text1)
val width2 = paint.measureText(text2)
var w2 = width2 / (width1 + width2)
if (w2 > 0.4f) {
w2 = 0.4f
}
val w1 = 1f - w2
// Second row
val text3 = "This text should take up more than 60% of the space"
val text4 = "Short"
val width3 = paint.measureText(text3)
val width4 = paint.measureText(text4)
var w4 = width4 / (width3 + width4)
if (w4 > 0.4f) {
w4 = 0.4f
}
val w3 = 1f - w4
setContent {
Column(modifier = Modifier.fillMaxSize()) {
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(bottom = 20.dp)
) {
Text(text1, modifier = Modifier.weight(w1))
Text(text2, modifier = Modifier.weight(w2), color = Color.Red)
}
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(bottom = 20.dp)
) {
Text(text3, modifier = Modifier.weight(w3))
Text(text4, modifier = Modifier.weight(w4), color = Color.Red)
}
}
}
}
}
Upvotes: 0