使用 SwipeToDismissBox 撤消 Snackbar

问题描述 投票:0回答:1

我开始使用 Jetpack Compose,并尝试实现一个列表,您可以在其中滑动以删除项目,但也可以通过 Snackbar 操作恢复它。在旧的基于 XML 布局的世界中,我之前成功做到了这一点,但我无法让它在 Jetpack Compose 中工作。

我可以添加滑动删除行为来成功删除该项目,之后我还可以显示 Snackbar。从技术上讲,将项目插入列表似乎也可行,但问题似乎是

rememberSwipeToDismissBoxState()
记得我刷过该项目并保持其状态。因此,当重新插入该项目时,检查状态以查看是否应删除该项目的
if
语句会立即触发并再次删除该项目。 该项目本身是一个保存在 SQLite 数据库中的实体,我可以通过 Room 访问该数据库。

有人知道如何甚至如果可以使用 Compose 实现这样的功能吗?

我目前有以下代码:

名单:

@Composable
fun WatchHistory(
    viewModel: WatchHistoryViewModel = viewModel(),
    navigator: Navigator = Navigator.current,
) {
    val entries = viewModel.entries.collectAsLazyPagingItems()
    val coroutineScope = rememberCoroutineScope()

    val snackbarHostState = remember { SnackbarHostState() }

    Scaffold(
        snackbarHost = {
            SnackbarHost(hostState = snackbarHostState)
        },
        topBar = {
            TopAppBar(
                title = {
                    Text(
                        text = stringResource(id = R.string.watch_history_title),
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                        modifier = Modifier.basicMarquee()
                    )
                },
                navigationIcon = {
                    IconButton(onClick = { navigator.back() }) {
                        Icon(
                            imageVector = Icons.AutoMirrored.Default.ArrowBack,
                            contentDescription = null
                        )
                    }
                },
                actions = { WatchHistoryMenu() },
            )
        },
        content = { contentPadding ->
            LazyColumn(contentPadding = contentPadding) {
                items(count = entries.itemCount, key = entries.itemKey { it.historyId }) { index ->
                    entries.get(index)?.let { item ->
                        WatchHistoryItem(
                            item = item,
                            onDelete = { id ->
                                coroutineScope.launch {
                                    viewModel.deleteEntry(id)

                                    val result =
                                        snackbarHostState.showSnackbar("Entry deleted", "Restore")

                                    if (result == SnackbarResult.ActionPerformed) {
                                        viewModel.undoDelete(item.toWatchHistoryEntry())
                                    }
                                }
                            }
                        )
                    }
                }
            }
        },
        contentWindowInsets = WindowInsets.safeDrawing
    )
}

商品:

@Composable
fun WatchHistoryItem(
    item: WatchHistoryVideoEntity,
    onDelete: (id: Int) -> Unit,
) {
    val swipeToDismissState = rememberSwipeToDismissBoxState()

    if (swipeToDismissState.currentValue == SwipeToDismissBoxValue.EndToStart) {
        onDelete(item.historyId)
    }

    SwipeToDismissBox(
        state = swipeToDismissState,
        backgroundContent = {}
    ) {
        VideoItem(item = item.video)
    }
}

实体。实际表包含

WatchHistoryEntryEntity
WatchHistoryVideoEntity
是通过与另一个表的联接创建的。

@Entity(tableName = "watchHistory", indices = [Index("watchDate")])
@JsonClass(generateAdapter = true)
data class WatchHistoryEntryEntity(
    @PrimaryKey(autoGenerate = true)
    override val id: Int = 0,

    @Json(name = "episodeId") val videoId: String,
    val watchDate: Instant = Instant.now()
) : BaseEntity<Int>

data class WatchHistoryVideoEntity(
    val historyId: Int,
    val watchDate: Instant,

    @Embedded val video: VideoEntity
) {
    fun toWatchHistoryEntry() = WatchHistoryEntryEntity(
        id = historyId,
        videoId = video.id,
        watchDate = watchDate,
    )
}
android android-jetpack-compose android-snackbar jetpack-compose-swipe-to-dismiss
1个回答
0
投票

我遇到了与此相关的问题 使用小吃栏操作恢复项目后 背景内容仍然卡住,直到我采取行动,例如过滤我传递给lazyColumn的列表以重构整个屏幕。

© www.soinside.com 2019 - 2024. All rights reserved.