DEV Community

myougaTheAxo
myougaTheAxo

Posted on

SwipeToDismiss完全ガイド — SwipeToDismissBox/背景アクション/Undo

この記事で学べること

SwipeToDismiss(SwipeToDismissBox、背景アクション表示、削除Undo、方向制御)を解説します。


SwipeToDismissBox

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SwipeDismissExample() {
    var items by remember { mutableStateOf(List(20) { "Item $it" }) }
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()

    Scaffold(snackbarHost = { SnackbarHost(snackbarHostState) }) { padding ->
        LazyColumn(Modifier.padding(padding)) {
            items(items, key = { it }) { item ->
                val dismissState = rememberSwipeToDismissBoxState(
                    confirmValueChange = { value ->
                        if (value == SwipeToDismissBoxValue.EndToStart) {
                            val deletedItem = item
                            items = items - item
                            scope.launch {
                                val result = snackbarHostState.showSnackbar(
                                    message = "${deletedItem}を削除",
                                    actionLabel = "元に戻す"
                                )
                                if (result == SnackbarResult.ActionPerformed) {
                                    items = items + deletedItem
                                }
                            }
                            true
                        } else false
                    }
                )

                SwipeToDismissBox(
                    state = dismissState,
                    backgroundContent = {
                        Box(
                            Modifier
                                .fillMaxSize()
                                .background(Color.Red)
                                .padding(horizontal = 20.dp),
                            contentAlignment = Alignment.CenterEnd
                        ) {
                            Icon(Icons.Default.Delete, "削除", tint = Color.White)
                        }
                    },
                    enableDismissFromStartToEnd = false
                ) {
                    ListItem(
                        headlineContent = { Text(item) },
                        modifier = Modifier.background(MaterialTheme.colorScheme.surface)
                    )
                }
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

双方向スワイプ

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BidirectionalSwipe(item: String, onDelete: () -> Unit, onArchive: () -> Unit) {
    val dismissState = rememberSwipeToDismissBoxState(
        confirmValueChange = { value ->
            when (value) {
                SwipeToDismissBoxValue.EndToStart -> { onDelete(); true }
                SwipeToDismissBoxValue.StartToEnd -> { onArchive(); true }
                else -> false
            }
        }
    )

    SwipeToDismissBox(
        state = dismissState,
        backgroundContent = {
            val direction = dismissState.dismissDirection
            val color = when (direction) {
                SwipeToDismissBoxValue.StartToEnd -> Color(0xFF4CAF50)
                SwipeToDismissBoxValue.EndToStart -> Color.Red
                else -> Color.Transparent
            }
            val icon = when (direction) {
                SwipeToDismissBoxValue.StartToEnd -> Icons.Default.Archive
                SwipeToDismissBoxValue.EndToStart -> Icons.Default.Delete
                else -> Icons.Default.Delete
            }
            val alignment = when (direction) {
                SwipeToDismissBoxValue.StartToEnd -> Alignment.CenterStart
                else -> Alignment.CenterEnd
            }
            Box(
                Modifier.fillMaxSize().background(color).padding(horizontal = 20.dp),
                contentAlignment = alignment
            ) { Icon(icon, null, tint = Color.White) }
        }
    ) {
        ListItem(
            headlineContent = { Text(item) },
            modifier = Modifier.background(MaterialTheme.colorScheme.surface)
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

まとめ

API 用途
SwipeToDismissBox スワイプ削除
SwipeToDismissBoxState スワイプ状態管理
confirmValueChange 削除確認
dismissDirection スワイプ方向判定
  • SwipeToDismissBoxでスワイプ削除/アーカイブ
  • backgroundContentで背景アクション表示
  • confirmValueChangeで確認/Undo実装
  • enableDismissFromStartToEndで方向制限

8種類のAndroidアプリテンプレート(リスト操作対応)を公開しています。

テンプレート一覧Gumroad

関連記事:


I publish 8 Android app templates on Gumroad.

Browse templatesGumroad

Top comments (0)