Home > Net >  Material Swipe To Dismiss in Jetpack Compose with a Column instead of a LazyColumn
Material Swipe To Dismiss in Jetpack Compose with a Column instead of a LazyColumn

Time:05-26

In my Jetpack Compose project I want to use Material SwipeToDismiss to delete an item with a swipe. In my composable I use a Column in a list instead of a LazyColumn. The problem is that when the item is deleted a recomposition starts and all following items are also deleted (because the dismissState seems to be the same for the next item). For example if the Column has 7 items and I delete item #5 then also item #6 and item #7 gets deleted.

It works if I use a LazyColumn (probably because of the keys) with a fixed height but I just want a list of items without scrolling or a fixed height. Any suggestions how to get this running?

@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun DocumentationsList(
    modifier: Modifier = Modifier,
    task: DBTask,
    documentations: List<DBDocumentation>,
    onDocumentationDelete: (DBDocumentation) -> Unit,
) {

    Column(
        modifier = modifier
    ) {
        for ((index, documentation) in documentations.withIndex()) {

            var dismissState = rememberDismissState(initialValue = DismissValue.Default)
            if (dismissState.isDismissed(DismissDirection.EndToStart)) {
                onDocumentationDelete(documentation)
            }

            SwipeToDismiss(
                state = dismissState,
                modifier = Modifier.padding(vertical = 4.dp),
                directions = setOf(DismissDirection.EndToStart),
                dismissThresholds = { direction ->
                    FractionalThreshold(if (direction == DismissDirection.StartToEnd) 0.25f else 0.5f)
                },
                background = {
                    val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
                    val color by animateColorAsState(
                        when (dismissState.targetValue) {
                            DismissValue.Default -> Color.LightGray
                            DismissValue.DismissedToEnd -> Color.Green
                            DismissValue.DismissedToStart -> Color.Red
                        }
                    )
                    val alignment = when (direction) {
                        DismissDirection.StartToEnd -> Alignment.CenterStart
                        DismissDirection.EndToStart -> Alignment.CenterEnd
                    }
                    val icon = when (direction) {
                        DismissDirection.StartToEnd -> Icons.Default.Done
                        DismissDirection.EndToStart -> Icons.Default.Delete
                    }
                    val scale by animateFloatAsState(
                        if (dismissState.targetValue == DismissValue.Default) 0.75f else 1f
                    )

                    Box(
                        Modifier.fillMaxSize().background(color).padding(horizontal = 20.dp),
                        contentAlignment = alignment
                    ) {
                        Icon(
                            icon,
                            contentDescription = "Localized description",
                            modifier = Modifier.scale(scale)
                        )
                    }
                },
                dismissContent = {
                    Card(
                        elevation = animateDpAsState(
                            if (dismissState.dismissDirection != null) 4.dp else 0.dp
                        ).value
                    ) {
                        
                        // Layout here
                    }
                }
            )
        }
    }

CodePudding user response:

You can use key which will work the same LazyColumn key parameter:

Column(
    modifier = modifier
) {
    for ((index, documentation) in documentations.withIndex()) {
        key(uniqueKey) {
            // your view
        }
    }
}

This should not be your index, as it will change for all items below the deleted one after deletion, it should be some identifier unique to each item in your collection.

  • Related