Home > front end >  Android compose Modifier width unexpected behaviour inside scrollable/lazy row
Android compose Modifier width unexpected behaviour inside scrollable/lazy row

Time:01-24

I am building a basic layout which diplays a horizontally scrollable row with cards. The cards are a column component with a couple dividers in the middle:

@Composable
fun TestCard(
  name: String
) {
  Column(
    modifier = Modifier
      .background(MaterialTheme.colors.surface)
      .padding(12.dp),
    horizontalAlignment = Alignment.Start
  ) {
    Text(text = name, style = Typography.h4.bold.black)
    Spacer(modifier = Modifier.height(8.dp))
    Divider(color = Color.Black) //DOES NOT APPEAR IN ROW
    Spacer(modifier = Modifier.height(8.dp))
    Divider(modifier = Modifier.fillMaxWidth(), color = Color.Black) //DOES NOT APPEAR IN ROW
    Spacer(modifier = Modifier.height(8.dp))
    Text(text = "Other text", style = Typography.h4.bold.black)
  }
}

I also have a scrollable row that contains a list of these cards:

@Composable
fun TestComponent() {

  val scrollState = rememberScrollState()
  val names = listOf("Martha", "Erik","Steve","Roy","Pete")

  Column(
    modifier = Modifier
      .fillMaxWidth()
      .background(MaterialTheme.colors.primary),
    horizontalAlignment = Alignment.Start
  ) {
    Row(Modifier.horizontalScroll(scrollState), horizontalArrangement = Arrangement.spacedBy(16.dp)) {
      names.forEach { name ->
        TestCard(name)
      }
    }
  }
}

When I display the card on its own, I can see both dividers. When I display the row containing cards the dividers don't appear, because their width is set to 0 (I can verify with LayoutInspector the dividers are there). Visual representation:

example

I know I can create a state variable for width that would be updated inside the Modifier.onSizeChanged but I am sure there must be a reason for this to happen and a better solution.

CodePudding user response:

The Divider has inside a fillMaxWidth() modifier, but as you check in the doc:

If the incoming maximum width is Constraints.Infinity this modifier will have no effect.

It happens because of the horizontalScroll.
You have to specify the width for the Dividers and the Spacers.

A workaround is to apply width(IntrinsicSize.Max) to the Column in the TestCard. In this way the Constraints have a Constraints.fixedWidth(width):

@Composable
fun TestCard(
    name: String
) {
    Column(
        modifier = Modifier
            .width(IntrinsicSize.Max)
            .background(androidx.compose.material.MaterialTheme.colors.surface)
            .padding(12.dp),
        horizontalAlignment = Alignment.Start
    ) {
        Text(text = name,)
        Spacer(modifier = Modifier.height(8.dp).fillMaxWidth())
        Divider(color = Color.Black, modifier = Modifier.fillMaxWidth()) 
        Spacer(modifier = Modifier.height(8.dp).fillMaxWidth())
        Divider(modifier = Modifier.fillMaxWidth(), color = Color.Black) 
        Spacer(modifier = Modifier.height(8.dp).fillMaxWidth())
        Text(text = "Other text" )
    }

} 
  • Related