Home > Software engineering >  JetpackCompose "Modifier.fillMaxHeight()" doesn't work in Card
JetpackCompose "Modifier.fillMaxHeight()" doesn't work in Card

Time:08-18

I’m thinking of placing one vertical line in a Card view, so I wrote these codes below, but it doesn't work well.

@Composable
fun ListScreen(
    title: String
) {
    Column {
        Scaffold(
            topBar = {
                TopAppBar(title = { Text(title) })
            }
        ) {
            Box(modifier = Modifier.fillMaxSize()) {
                List()
            }
        }
    }
}

@Composable
fun List(
    modifier: Modifier = Modifier
) {

    val testList = listOf("test1", "test2")

    LazyColumn(
        modifier = modifier
    ) {
        items(
            items = testList
        ) { testText ->

            Card (
                elevation = 10.dp,
                modifier = modifier
                    .fillMaxSize() // It doesn't work.
                    .padding(
                        top = 30.dp,
                        start = 30.dp,
                        end = 30.dp,
                        bottom = 30.dp
                    )
                    .border(
                        width = 0.8.dp,
                        color = Color.DarkGray,
                        shape = RectangleShape
                    )
            ) {
                Row {
                    Text(
                        text = testText,
                        fontSize = 30.sp,
                        modifier =
                        Modifier
                            .padding(horizontal = 15.dp, vertical = 20.dp)
                            .weight(0.5f)
                    )

                    Divider(
                        modifier = Modifier
                            .fillMaxHeight() // <-  It doesn't work.
                            .width(0.5.dp),
                        color = Color.Black
                    )

                }

            }
        }
    }
}

I imagined that my screen was to look like the following image, but actually showed one with no yellow line. That means Divider in Row doesn't work.

My ideal image of application:
my ideal image of application

To solve this problem,

  1. I checked whether both Modifier.width and height work well.

    I actually specified dp for height and width and it worked fine.

  2. I tried using Modifier.onSizeChanged().

var dividerHeight by remember { mutableStateOf(50.dp) }

Row {
       Text(
            text = testText,
            fontSize = 30.sp,
            modifier =
              Modifier
                  .padding(horizontal = 10.dp, vertical = 10.dp)
                  .weight(0.5f)
        )

        Divider(
            modifier = Modifier
                      .height(dividerHeight) // set a default value
                      .width(0.5.dp)
                      .onSizeChanged { dividerHeight = it.height.dp }, // added this line
            color = Color.DarkGray
       )
}

This certainly worked at one time as shown above, but when the height changed, only the height of the Divider remained the same. In addition, I tried replacing onSizeChanged { } and height(), but it threw the following error. java.lang.IllegalArgumentException: Can't represent a size of 348160 in Constraints

What should I do next to solve this problem?

CodePudding user response:

The reason for both .fillMaxSize() and .fillMaxHeight() not working in the commented line is given in documentation as follows.

fillMaxSize

Have the content fill (possibly only partially) the Constraints.maxWidth and Constraints.maxHeight of the incoming measurement constraints, by setting the minimum width and the maximum width to be equal to the maximum width multiplied by fraction, as well as the minimum height and the maximum height to be equal to the maximum height multiplied by fraction. Note that, by default, the fraction is 1, so the modifier will make the content fill the whole available space. If the incoming maximum width or height is Constraints.Infinity this modifier will have no effect in that dimension.

fillMaxHeight

Have the content fill (possibly only partially) the Constraints.maxHeight of the incoming measurement constraints, by setting the minimum height and the maximum height to be equal to the maximum height multiplied by fraction. Note that, by default, the fraction is 1, so the modifier will make the content fill the whole available height. If the incoming maximum height is Constraints.Infinity this modifier will have no effect.

If you notice the last line for both,
f the incoming maximum width or height is Constraints.Infinity this modifier will have no effect in that dimension.

What it means if you use a Composable like LazyColumn, it does not have a height constraint since it is scrollable. It has Constraints.Infinity as the height constraint. When you specify to use fillMaxSize, it is impossible to give infinity height. So it is ignored.

Same logic for fillMaxHeight.

P.S: fillMaxSize does work. If you remove it, you would see that the card no longer fills the entire device width.


So how do we fix this?

Well you have to give some height constraints. Fixed or programatically.

  • Related