How to update a single row in a LazyColumn?

105 views Asked by At

I have an Android Jetpack Compose screen. I am showing a list of things that includes an image and some text on each row. I have implemented LazyRow to do this.

enter image description here

I would like to add the following feature: when I click on any row, I show an additional text in the row. Another click will hide this additional text. So a click on a list row behaves like a toggle.

Is there a way to granularly update a specific row? I have a viewModel that backs the data for this composable. But if I force a refresh with the whole list with one row updated, it recomposes the image for all the rows which wasteful.

What is the recommended way to do this in compose? I can't find any way to update a single row of a lazyColumn.

Is there a way to cache the painter object so that it does not get recreated unncesserarily? I am beginning to miss the good old RecyclerView!

 LazyColumn(modifier) {
    this.itemsIndexed(flags, key = {_, flagData -> "${flagData.countryName}:${flagData.group} "}) {index, flagData ->
        RenderFlagRow(index, flagData, onRowClicked)
        HorizontalDivider(modifier = Modifier.fillMaxWidth(), thickness = 2.dp, color = Color.LightGray)
    }
}
1

There are 1 answers

2
Rafael Moreira On

Well, one of the ways is just creating a conditional based on a trigger/saved value.

If the user clicks the DogItemButton, the box will expand in the row and show the extra information. But you can just show whatever you're thinking.

@Composable
fun DogItem(dog: Dog, modifier: Modifier = Modifier) {

// var expanded will be used to track whether the dog item is expanded.
   
    var expanded by remember { mutableStateOf(false) }
    Card(modifier = modifier) {
        Column(
            modifier = modifier
                .animateContentSize(
                    animationSpec = spring(
                        dampingRatio = Spring.DampingRatioLowBouncy,
                        stiffness = Spring.StiffnessMedium
                    )
                )
        ) {
            Row(modifier = Modifier.fillMaxWidth()) {
                DogIcon(dog.imageResourceId)
                DogInformation(dog.name, dog.age)
                Spacer(modifier = Modifier.weight(1f))
                DogItemButton(expanded = expanded, onClick = { expanded = !expanded })
            }
            if (expanded) {
                DogHobby(
                    dogHobby = dog.hobbies,
                    modifier = Modifier.padding(
                        start = dimensionResource(id = R.dimen.padding_medium),
                        top = dimensionResource(id = R.dimen.padding_small),
                        end = dimensionResource(id = R.dimen.padding_medium),
                        bottom = dimensionResource(id = R.dimen.padding_medium)
                    )
                )
            }
        }
    }
}

Here's the Scaffold used with the lazyColumn.

Scaffold(
        topBar = { WoofTopAppBar() },
    ) { it ->
        LazyColumn(contentPadding = it) {
            items(dogs) {
                DogItem(
                    dog = it,
                    modifier = Modifier.padding(dimensionResource(R.dimen.padding_small))
                )
            }
        }
    }