ダイアログやSnackbarによるユーザー通知の実装【Jetpack Compose入門⑩】

ユーザー通知とは?

通知の重要性

アプリ開発において、ユーザーへ適切なタイミングで情報を伝えることは重要です。ユーザーの操作に対するフィードバックや、重要な情報の伝達を行うことで、アプリのユーザビリティが向上します。

Jetpack Composeにおける通知手段

Jetpack Composeでは、主に以下の2つの方法でユーザーに通知を行います。

  1. ダイアログ(Dialog):ユーザーに重要な情報を伝えたり、確認を求める際に使用。
  2. Snackbar:短時間でユーザーに通知を伝える方法。

本記事では、Jetpack ComposeにおけるダイアログとSnackbarの実装方法を解説します。

ダイアログの実装

基本的なダイアログの作成

ダイアログはAlertDialogコンポーネントを使用して実装できます。

@Composable
fun SimpleDialog(showDialog: Boolean, onDismiss: () -> Unit) {
    if (showDialog) {
        AlertDialog(
            onDismissRequest = onDismiss,
            title = { Text(text = "注意") },
            text = { Text(text = "この操作を実行しますか?") },
            confirmButton = {
                Button(onClick = onDismiss) {
                    Text("OK")
                }
            },
            dismissButton = {
                Button(onClick = onDismiss) {
                    Text("キャンセル")
                }
            }
        )
    }
}

ダイアログの表示制御

rememberを使用して、ダイアログの表示状態を管理できます。

@Composable
fun DialogExample() {
    var showDialog by remember { mutableStateOf(false) }
    
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Button(onClick = { showDialog = true }) {
            Text("ダイアログを表示")
        }
        
        SimpleDialog(showDialog = showDialog, onDismiss = { showDialog = false })
    }
}

カスタムダイアログの作成

独自デザインのダイアログ

標準のAlertDialogではなく、Dialogコンポーネントを使用してカスタムデザインのダイアログを作成できます。

@Composable
fun CustomDialog(showDialog: Boolean, onDismiss: () -> Unit) {
    if (showDialog) {
        Dialog(onDismissRequest = onDismiss) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp)
                    .background(Color.White, shape = RoundedCornerShape(8.dp)),
                contentAlignment = Alignment.Center
            ) {
                Column(modifier = Modifier.padding(16.dp)) {
                    Text(text = "カスタムダイアログ", fontSize = 20.sp)
                    Spacer(modifier = Modifier.height(8.dp))
                    Button(onClick = onDismiss) {
                        Text("閉じる")
                    }
                }
            }
        }
    }
}

Snackbarの実装

基本的なSnackbarの表示

Snackbarは、短時間表示されるユーザー通知に適しています。

@Composable
fun SimpleSnackbarExample() {
    val snackbarHostState = remember { SnackbarHostState() }
    val coroutineScope = rememberCoroutineScope()
    
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Button(onClick = {
            coroutineScope.launch {
                snackbarHostState.showSnackbar("操作が完了しました")
            }
        }) {
            Text("Snackbarを表示")
        }
        
        SnackbarHost(hostState = snackbarHostState)
    }
}

Snackbarのカスタマイズ

カスタムボタン付きのSnackbarを作成することもできます。

@Composable
fun CustomSnackbarExample() {
    val snackbarHostState = remember { SnackbarHostState() }
    val coroutineScope = rememberCoroutineScope()
    
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Button(onClick = {
            coroutineScope.launch {
                snackbarHostState.showSnackbar(
                    message = "変更を保存しました",
                    actionLabel = "元に戻す",
                    duration = SnackbarDuration.Long
                )
            }
        }) {
            Text("Snackbarを表示")
        }
        
        SnackbarHost(hostState = snackbarHostState)
    }
}

ダイアログとSnackbarの組み合わせ

ダイアログとSnackbarを組み合わせることで、よりリッチなユーザー体験を提供できます。

@Composable
fun DialogWithSnackbarExample() {
    var showDialog by remember { mutableStateOf(false) }
    val snackbarHostState = remember { SnackbarHostState() }
    val coroutineScope = rememberCoroutineScope()
    
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Button(onClick = { showDialog = true }) {
            Text("操作を開始")
        }
        
        if (showDialog) {
            AlertDialog(
                onDismissRequest = { showDialog = false },
                title = { Text("確認") },
                text = { Text("本当に実行しますか?") },
                confirmButton = {
                    Button(onClick = {
                        showDialog = false
                        coroutineScope.launch {
                            snackbarHostState.showSnackbar("操作が完了しました")
                        }
                    }) {
                        Text("OK")
                    }
                },
                dismissButton = {
                    Button(onClick = { showDialog = false }) {
                        Text("キャンセル")
                    }
                }
            )
        }
        
        SnackbarHost(hostState = snackbarHostState)
    }
}

まとめ

  • ダイアログ(Dialog) は、重要な確認やユーザー入力に適した通知方法。
  • Snackbar は、短時間でユーザーへ通知を行う方法。
  • カスタムデザインのダイアログ を作成することで、より洗練されたUXを提供可能。
  • Snackbarとダイアログを組み合わせる ことで、よりインタラクティブなユーザー体験を実現。

Jetpack Composeを活用して、最適なユーザー通知を設計し、アプリの使いやすさを向上させましょう!