Reputation: 907
I am making a layout where a column contains up to 5 rows. Each row has three columns and I would like to have the width of the first column of each row be completely equal.
The first column in each row always takes up as much size as the text it contains, the size of the column doesn't scale to match the size of the biggest column in the list of rows.
Each row item:
fun GetRowItem(firstColumnText: String, secondColumnText: String, thirdColumnText: String) {
Row(
modifier = Modifier.padding(start = 4.dp, end = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.padding(end = 4.dp),
) {
Text(
text = firstColumnText
)
}
Column(
modifier = Modifier.padding(end = 4.dp),
) {
Text(
text = secondColumnText
)
}
Column(
modifier = Modifier.padding(end = 4.dp),
) {
Text(
text = thirdColumnText
)
}
}
}
Then I have a parent that arranges the rows something like this:
Column(modifier = Modifier.fillMaxWidth().padding(start = 8.dp, end = 8.dp) {
GetRowItem(firstColumnText = "short", secondColumnText = "something", thirdColumnText = "something")
GetRowItem(firstColumnText = "Realy long ee", secondColumnText = "something", thirdColumnText = "something")
GetRowItem(firstColumnText = "1", secondColumnText = "something", thirdColumnText = "something")
}
The output of this is not what I am looking for and I am struggling to see how to align the columns in each row item. It looks like InstrisicSize
might be an option here, but I'm not sure how to get the max size of an arbitrary column in the list of rows and apply it to each column. The image below shows what I am getting versus what I am expecting. I only want to align the first columns, the rest don't matter.
Upvotes: 7
Views: 3034
Reputation: 4858
You can use a MutableState<Dp>
which stores the maximum width. This width is set as minWidth for the first child composable of the row. The width is updated if there is any first child which exceeds the current width.
Note: The MutableState
must be created in the scope of the parent (Column).
@Preview(showBackground = true)
@Composable
fun LabeledColumn() {
Column {
var firstColumnWidth by remember { mutableStateOf(0.dp) }
val density = LocalDensity.current
repeat(10) {
Row {
Text(
text = List(it + 1) { i -> "$i" }.joinToString(),
modifier = Modifier
.defaultMinSize(firstColumnWidth)
.onPlaced {
val widhtDp = density.run { it.size.width.toDp() }
firstColumnWidth = max(firstColumnWidth, widhtDp)
}
)
Text(text = "column 1", modifier = Modifier.weight(1f))
Text(text = "column 2", modifier = Modifier.weight(1f))
}
}
}
}
Upvotes: 0
Reputation: 617
maybe it could help
Column(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
) {
}
if you want the center column to be wider than the left and right column you can set the weight of the center column 2 and left and right 1, or you can set the width of columns for example to 100 dp or 200 dp, and set horizontalArrangement of your row to Arrangement.SpaceBetween to have some margin around the columns
Upvotes: 0
Reputation: 1465
I have found a way to solve your issue
Get Row Item
@Composable
fun GetRowItem(firstColumnText: String, secondColumnText: String, thirdColumnText: String, width: State<Int>, widthCallback: (Int) -> Unit) {
val widthInDp = with(LocalDensity.current) {
width.value.toDp()
}
Row(
modifier = Modifier.padding(start = 4.dp, end = 4.dp),
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.padding(end = 4.dp),
) {
if (widthInDp == 0.dp) {
Text(
text = firstColumnText,
modifier = Modifier.onGloballyPositioned {
widthCallback(it.size.width)
}
)
}else {
Text(
text = firstColumnText,
modifier = Modifier.width(width = widthInDp)
)
}
}
Column(
modifier = Modifier.padding(end = 4.dp),
) {
Text(
text = secondColumnText
)
}
Column(
modifier = Modifier.padding(end = 4.dp),
) {
Text(
text = thirdColumnText
)
}
}
}
Parent code that holds the row
Surface(color = MaterialTheme.colors.background) {
val width = remember {
mutableStateOf(0)
}
Column(
modifier = Modifier
.fillMaxSize()
.padding(start = 8.dp, end = 8.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
GetRowItem(firstColumnText = "short", secondColumnText = "something", thirdColumnText = "something", width = width) {
if (it > width.value) {
width.value = it
}
}
GetRowItem(firstColumnText = "Realy long ee", secondColumnText = "something", thirdColumnText = "something", width = width) {
if (it > width.value) {
width.value = it
}
}
GetRowItem(firstColumnText = "1", secondColumnText = "something", thirdColumnText = "something", width = width) {
if (it > width.value) {
width.value = it
}
}
}
}
}
}
}
I'have added surface
and modified column
to fillMaxSize()
so you can test this
Upvotes: 0
Reputation: 3099
An easy way to achieve this would be to give each of the columns the same weight.
Column(modifier = Modifier.weight(1f)){
// text
}
Upvotes: 2