0

Following problem: I created a Compose View which should display a item list (it also should display more things in future development).

I created following view:

data class ItemHolder(
    val header: String,
    val subItems: List<String>,
    val footer: String
)

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Create items
        val items = (1..20).map { itemIndex ->
            ItemHolder(
                header = "Header of $itemIndex",
                subItems =  (1..30).map { subItemIndex ->
                    "Sub item $subItemIndex of $itemIndex"
                },
                footer = "Footer of $itemIndex"
            )
        }

        setContent {
            Column(
                modifier = Modifier.verticalScroll(rememberScrollState())
            ) {
                Text(text = "Items:")
                ItemList(items = items)
            }
        }
    }
}

// Displays the list of items
@Composable
fun ItemList(items: List<ItemHolder>) {
    LazyColumn {
        items(items = items) {
            Item(item = it)
        }
    }
}

// Displays a single item
@Composable
fun Item(item: ItemHolder) {
    var subItemsVisible by remember { mutableStateOf(false) }

    // Displays the header of the item
    Row {
        Text(text = item.header)
        Button(
            onClick = { subItemsVisible = !subItemsVisible },
            content = {
                Text(text = if (subItemsVisible) "Hide" else "Show")
            }
        )
    }

    // Displays the sub items of the item
    AnimatedVisibility(visible = subItemsVisible) {
        Column {
            for (subItem in item.subItems) {
                Text(text = subItem)
            }
        }
    }

    // Displays the footer of the item
    Text(text = item.footer)
}

I found out that the problem is, that the outer Column (which is scrollable) contains the LazyColumn which contains the actual items.

I get following error:

java.lang.IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed.

I was searching around for hours, but didn't find any suitable solution for my problem. How can I fix this?

Daniel
  • 380
  • 2
  • 14
  • Don't use a LazyColumn inside a scrollable column – Gabriele Mariotti Feb 06 '23 at 11:16
  • Well, this solved my Problem but then the advantages of LazyColumn get lost. – Daniel Feb 06 '23 at 11:40
  • 1
    Simply don't measure your LazyColumn with `Constraints.Infinity`. One way to overcome this is to use `Modifier.heightIn(max=...)` to change infinite max Height to something finite while not giving your LazyColumn a fixed height but biggest height it can be measured with. https://stackoverflow.com/a/75219930/5457853 Other one is to add everything in `item` and/or `items`like structure to have one lazyColumn with single or multiple items while using one LazyColumn – Thracian Feb 06 '23 at 17:21

2 Answers2

1

I think you have to remove modifier = Modifier.verticalScroll(rememberScrollState()) it will not work with nested lazy column

refer this link may be help you :https://proandroiddev.com/nested-scroll-with-jetpack-compose-9c3b054d2e12

I edit your code I hope it will help you

data class ItemHolder(
    val header: String,
    val subItems: List<String>,
    val footer: String
)

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val items = (1..4).map { itemIndex ->
            ItemHolder(
                header = "Header of $itemIndex",
                subItems = (1..30).map { subItemIndex ->
                    "Sub item $subItemIndex of $itemIndex"
                },
                footer = "Footer of $itemIndex"
            )
        }

        setContent {
            LazyColumn(
                modifier = Modifier.padding(10.dp)
            ) {
                item {
                    Text(text = "Items: Header", color = Color.Red, fontSize = 20.sp)
                    Spacer(modifier = Modifier.height(20.dp))
                }
                items(items = items) {
                    Item(item = it)
                }
                item {
                    Spacer(modifier = Modifier.height(20.dp))
                    Text(text = "Items: Footer", color = Color.Red, fontSize = 20.sp)
                    Spacer(modifier = Modifier.height(20.dp))
                }
                items(items = items) {
                    Item(item = it)
                }
            }
        }
    }
}


// Displays a single item
@Composable
fun Item(item: ItemHolder) {
    var subItemsVisible by remember { mutableStateOf(false) }

    // Displays the header of the item
    Row {
        Text(text = item.header)
        Button(
            onClick = { subItemsVisible = !subItemsVisible },
            content = {
                Text(text = if (subItemsVisible) "Hide" else "Show")
            }
        )
    }

    // Displays the sub items of the item
    AnimatedVisibility(visible = subItemsVisible) {
        Column {
            for (subItem in item.subItems) {
                Text(text = subItem)
            }
        }
    }

    // Displays the footer of the item
    Text(text = item.footer)
}

enter image description here

Heet Changela
  • 565
  • 1
  • 11
1

Simply you can replace LazyColumn by Column as follows:

// Displays the list of items
@Composable
fun ItemList(items: List<ItemHolder>) {
    Column {
        items.indices.forEach { i ->
            Item(item = items[i])
        }
    }
}
Pillocron
  • 141
  • 1
  • 6