rslemos
rslemos

Reputation: 2730

LazyColumn (and ScalingLazyColumn) with variable height items in Wear OS

I don't know if I've stepped in a LazyColumn bug or maybe I'm doing something wrong.

It looks like LazyColumn takes the first four† items' height and repeats them for the next elements.

Consider the following preview:

@WearPreviewLargeRound
@Composable
fun DefaultPreview() {
    LazyColumn(
        modifier = Modifier.fillMaxSize().padding(all = 20.dp),
        state = rememberLazyListState()
    ) {
        val cardSizes = listOf(2, 3, 4, 5, 1, 2, 3, 4, 3, 4, 5, 6, 1, 1, 1, 1)

        itemsIndexed(cardSizes) { i, lines ->
            Card(
                modifier = Modifier.fillMaxWidth().border(1.dp, color = Color.White),
                onClick = { },
            ) {
                Text("${i}. ${lines} lines", color = Color.Red)
                Text("- line" + "\n- line".repeat(lines - 1), color = Color.Green)
                Text("------", color = Color.Cyan, modifier = Modifier.border(1.dp, color = Color.Cyan))
            }
        }
    }
}

What I expect: a full-sized LazyColumn containing variable sized cards. Each card should display a variable number of lines (or at least that is what I expect).

As I said earlier, the first 4 items are exactly what I expect them to be.

Now look at the 5th item (index 4):

index 4 displays more space than expected

It clearly shows more space than expected. The 5th card was alloted space for a 2-lines card (the same height as the 1st item).

Now look at the 6th item (index 5):

index 5 displays more space than expected

Again. Now the 6th card has (unnecessarily) the same height as the 2nd card.

I'll skip the 7th and 8th cards (spoiler: the same happens).

Then comes the 9th card (index 8):

index 8 displays less space than expected

The 9th card needs space for 3 lines, but couldn't get it. Instead it gets space for 2 lines (suspiciously the same as the 1st card).

The same happens to 10th, 11th and 12th cards (less space than they need, but the same space as 2nd, 3rd and 4th cards).

Let me jump to the 16th card (index 15):

index 15 displays way more space than needed

The 16th card though bearing just 1 line, gets space for 5 lines (repeating the 4th card).

I could only reproduce this behavior in Wear OS.

† it depends on device height

EDIT

After tweaking the code a little now I think the culprit maybe the Text component. Whenever there is a Text with multiple lines (either a big text that gets wrapped automatically or text with \n sprinkled here and there), it looks like sometimes Text occupies more vertical space than it announces to its parent container (still I cannot explain the other case, when it "announces" more space than it really occupies).

If only I knew a bit more about composition, maybe I could debug it further.

EDIT 2

I kept tweaking even more.

Now I replaced LazyColumn to Column (plus Modifier.verticalScroll(...) and cardSizes.forEachIndexed instead of itemsIndexed(cardSizes)) and then each item has the exact size they have to. No slack space, no cropped content.

I'm still clueless.

Upvotes: 2

Views: 385

Answers (0)

Related Questions