Home > Software design >  Compose stops after function
Compose stops after function

Time:01-22

I want to have two tables below each other in my app and I used this code as a template for a table. The problem is that when I call the table component, everything after it won't be executed. It doesn't show any error or anything in logcat so I have no idea what is causing it.

Main:

Column {
    MyTable(someData = mylist) // will show

    
    Text(text = "Hello") // won't show
    MyTable(someData = mylist) // won't show
}

MyTable.kt

data class Cell(
    val name: String,
    val weight: Float
)

@Composable
fun RowScope.TableCell(...) { /* same as in the linked code */ }

@Composable
fun MyTable(data: List<Something>) {
    val columns = listOf(
        Cell("a", .25f),
        Cell("b", .25f),
        Cell("c", .25f),
        Cell("d", .25f)
    )

    LazyColumn(
        Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        item {
            Row {
                columns.forEach {
                    TableCell(
                        text = it.name,
                        weight = it.weight
                    )
                }
            }
        }

        itemsIndexed(data) { ind, item ->
            Row(Modifier.fillMaxWidth()) {
                TableCell(
                    text = item.somenumber.toString(),
                    weight = columns[0].weight
                )

                TableCell(
                    text = "Abc",
                    weight = columns[1].weight
                )

                TableCell(
                    text = item.somestring1,
                    weight = columns[2].weight
                )

                TableCell(
                    text = item.somestring2,
                    weight = columns[3].weight
                )
            }
        }
    }
}

CodePudding user response:

Lazy column in your table have fillMaxSize modifier so it will always claim all space the parent can provide. To display one table under the other you would have to set it to wrapContentSize which basically defeats the whole purpose of lazy column. To do all of this properly you should nest everything in single lazy column. Display header as a simple item and then rows as items underneath the header. It will work, but in my experience lazy column is not there yet in terms of performance (in case of lazy column with different children type). So maybe for that particular case I would stick with the good old recyclerview

CodePudding user response:

You should remove thefillMaxSize() from your LazyColumn()

@Composable
    fun MyTable(data: List<Something>) {
        val columns = listOf(
            Cell("a", .25f),
            Cell("b", .25f),
            Cell("c", .25f),
            Cell("d", .25f)
        )

    LazyColumn(
        Modifier //Removed
            .padding(16.dp)
    ) {

CodePudding user response:

As @Jakoss correctly pointed out, the first view with Modifier.fillMaxHeight(1f /* default value */) inside Column will take up all available space, so other views are not visible.

The solution depends on how you expect your final layout to work.

  1. If you want to see both tables on the screen at the same time, and scroll each independently of the other, you can apply the Modifier.weight(1f) to each of them - this will make them the same size and fill height. This modifier is part of ColumnScope, so you need to pass it as a parameter of your MyTable:

    MyTable:

    @Composable
    fun MyTable(
        data: List<Something>
        modifier: Modifier,
    ) {
        // ..
    
        LazyColumn(
            modifier
                .padding(16.dp)
        ) {
            // ..
    

    Main:

    Column {
        MyTable(
            someData = mylist,
            modifier = Modifier
                .weight(1f)
        )
    
        Text(text = "Hello")
    
        MyTable(
            someData = mylist,
            modifier = Modifier
                .weight(1f)
        )
    }
    
  2. The other case is if you want to have one scrollable table with two "subtables". In that case, you should have only one `LazyColumn', and both subtables as elements inside. Something like this:

    Main:

    LazyColumn {
        myTableItems(data = mylist)
        item {
            Text(text = "Hello")
        }
        myTableItems(data = mylist)
    }
    

    myTableItems:

    fun LazyListScope.myTableItems(data: List<Something>) {
        val columns = listOf(
            Cell("a", .25f),
            Cell("b", .25f),
            Cell("c", .25f),
            Cell("d", .25f)
        )
        item {
            Row {
                columns.forEach {
                    TableCell(
                        text = it.name,
                        weight = it.weight
                    )
                }
            }
        }
    
        itemsIndexed(data) { ind, item ->
            Row(Modifier.fillMaxWidth()) {
                TableCell(
                    text = item.somenumber.toString(),
                    weight = columns[0].weight
                )
                // other cells
            }
        }
    }
    
  •  Tags:  
  • Related