Search code examples
androidandroid-jetpack-composeandroid-jetpack-compose-material3lazycolumnandroid-jetpack-compose-lazy-column

Making Tabs with scrollable content scroll alongside parent composable - IllegalException: Infinity maximum height


I have a composable screen which has some content, then a TabRow, which holds different screens (depending on the selected tab). The tab screens contain scrollable data and this is shown using a LazyColumn.

On the parent screen, I only have a parent Column. I want this column to be scrollable as well as the content on my Tab screens. (Because orientation change, small screen size, etc. See attached screenshots).

The problem is I can't have my parent screen Column while having the Tab screens use a LazyColumn. I get the error:

java.lang.IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed. One of the common reasons is nesting layouts like LazyColumn and Column(Modifier.verticalScroll()). If you want to add a header before the list of items please add a header as a separate item() before the main items() inside the LazyColumn scope. There are could be other reasons for this to happen: your ComposeView was added into a LinearLayout with some weight, you applied Modifier.wrapContentSize(unbounded = true) or wrote a custom layout. Please try to remove the source of infinite constraints in the hierarchy above the scrolling container.

How can I achieve this goal of having both the parent screen scrollable (for smaller screens) and having the content in my Tab screens scrollable as well?

enter image description here

enter image description here


Solution

  • Answer for anyone facing a similar challenge:

    I discovered LazyListScope. So instead of creating another composable for each tab, I created a function within the parent composable which loaded the list to be recycled. I also changed the parent Column to a LazyColumn and added the content in it as individual items.

    Here is my new LazyListScope function:

    fun LazyListScope.transactionsScreen() {
        val transactions = listOf(
           // Transaction items here
        )
        itemsIndexed(transactions){index, transaction ->
            TransactionItem(transaction = transaction)
        }
    }