0

I have some LazyColumn (or Column) in Composable fun:

@Composable
fun MyColumn(items: List<Item>) {
    val width = 0.dp // max for all amounts
    LazyColumn {
        items(items) {
            Row(modifier = Modifier.fillMaxWidth()) {
                Text(text = it.title, modifier = Modifier.weight(1f))
                Text(text = it.amount, modifier = Modifier.background(Color.Red).width(width))
            }
        }
    }
}

class Item(val title: String, val amount: String)

How can I measure the width param? It must be equals the longest value for all amounts in items.

Christina
  • 55
  • 5
  • 1
    You need to use SubcomposeLayout to get longest width and call subcompose and measue all of the composable to this width. You can check out answers below. https://stackoverflow.com/a/70383797/5457853 https://stackoverflow.com/questions/70361098/jetpack-compose-set-sibling-composables-width-to-longest-one-dynamically-with-s – Thracian Jan 25 '23 at 16:08
  • https://stackoverflow.com/questions/72925896/how-can-i-make-the-two-buttons-the-same-width-when-i-use-jetpack-compose/72940620#72940620 – Thracian Jan 25 '23 at 17:07
  • Thanks, I got it, but when I launch my LazyColumn after width's measuring, it crashes with java.lang.IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints – Christina Jan 25 '23 at 17:40
  • How do you use it? LazyColumn cannot be measured with Constraints.Infinity as max height while LazyRow not with max width as Constraints.Infinity. And using a SubcomposeLayout instead of Row shouldn't throw exception – Thracian Jan 25 '23 at 17:47
  • So. I thought better and realized that I didn't understand anything. Could you write specifically where exactly I should use SubComposeLayout - for each row in the column or for the entire column? I understand how SubComposeLayout can help in changing the size within a single row, but how do I take the longest width of the amount among ALL rows into the column. I don't understand at all. – Christina Jan 26 '23 at 14:47

1 Answers1

0

Finally I got some solution (I don't know is it correct or no, but it works):

  1. I use SubcomposeLayout to measure width of whole separate column with amounts. Code of the measuring function:

     @Composable
     fun WithCalculateWidth(modifier: Modifier = Modifier,
                            contentForCalculate: @Composable () -> Unit,
                            dependentContent: @Composable (Dp) -> Unit) {
         SubcomposeLayout(modifier = modifier) { constraints ->
             val measuredWidth = subcompose("viewToMeasure", contentForCalculate)[0].measure(Constraints()).width.toDp()
             val contentPlaceable = subcompose("content") { dependentContent(measuredWidth) }[0].measure(constraints)
             layout(contentPlaceable.width, contentPlaceable.height) {
                 contentPlaceable.place(0, 0)
             }
         }
     }
    
  2. I use calculated width in my List:

     @Composable
     fun ListWithMeasuredAmounts(items: List<Item>) {
         val allAmounts: @Composable () -> Unit = {
             Column {
                 items.forEach {
                     AmountItem(amount = it.amount)
                 }
             }
         }
    
         WithCalculateWidth(contentForCalculate = { allAmounts() }) { amountWidth ->
             LazyColumn {
                 items(items) {
                     Row(modifier = Modifier.fillMaxWidth()) {
                         Text(text = it.title, modifier = Modifier.weight(1f))
                         AmountItem(amount = it.amount, modifier = Modifier.width(amountWidth))
                     }
                 }
             }
         }
     }
    
     @Composable
     fun AmountItem(amount: String, modifier: Modifier = Modifier) {
         Text(text = amount, modifier = modifier.background(Color.Red))
     }
    
Christina
  • 55
  • 5
  • Your code crashes with IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints – Andrew Kolubov Aug 05 '23 at 16:01