Compose 中的 Snackbar

596 阅读2分钟

在 Jetpack Compose 中,Snackbar 是一种临时显示的信息提示,用于向用户提供有关操作的简要消息。Snackbar 通常显示在屏幕底部,并在一段时间后自动消失,或者用户可以手动关闭它。

Snackbar 的使用

Snackbar 通常与 Scaffold 组件一起使用,因为 Scaffold 提供了一个 snackbarHost 参数,用于管理和显示 Snackbar。使用 SnackbarHostState 来管理 Snackbar 的状态和显示。

主要组件和参数

  • SnackbarHostState: 管理 Snackbar 的状态。
  • Scaffold: 提供应用的基本布局结构,包含 snackbarHost 参数。
  • Snackbar: 用于显示临时消息。

示例代码

以下是一个基本的示例代码,展示如何在 Jetpack Compose 中使用 Snackbar

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SnackbarExampleTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    SnackbarExample()
                }
            }
        }
    }
}

@Composable
fun SnackbarExample() {
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()

    Scaffold(
        snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
        topBar = {
            TopAppBar(
                title = { Text("Snackbar Example") }
            )
        },
        content = { innerPadding ->
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(innerPadding),
                contentAlignment = Alignment.Center
            ) {
                Button(onClick = {
                    scope.launch {
                        snackbarHostState.showSnackbar(
                            message = "This is a Snackbar",
                            actionLabel = "Dismiss",
                            duration = SnackbarDuration.Short
                        )
                    }
                }) {
                    Text("Show Snackbar")
                }
            }
        }
    )
}

@Preview(showBackground = true)
@Composable
fun SnackbarExamplePreview() {
    SnackbarExampleTheme {
        SnackbarExample()
    }
}

解释

  1. 状态管理:

    • 使用 remember { SnackbarHostState() } 来管理 Snackbar 的状态。
    • 使用 rememberCoroutineScope 来处理 Snackbar 的显示和隐藏。
  2. 布局:

    • 使用 Scaffold 提供应用的基本布局结构,包括 TopAppBar 和内容区域。
    • 使用 Box 布局将按钮居中显示在屏幕上。
  3. SnackbarHost:

    • SnackbarHostScaffold 的一个参数,用于管理和显示 Snackbar
  4. 显示 Snackbar:

    • 使用 scope.launch 来启动协程,并调用 snackbarHostState.showSnackbar 来显示 Snackbar
    • showSnackbar 方法有多个参数:message 是要显示的消息,actionLabel 是可选的操作标签(例如“Dismiss”),duration 是显示时长。

自定义 Snackbar

你可以通过自定义 Snackbar 组件来修改其外观,例如背景颜色、文本颜色等:

@Composable
fun CustomSnackbar(snackbarHostState: SnackbarHostState) {
    SnackbarHost(
        hostState = snackbarHostState,
        snackbar = { snackbarData ->
            Snackbar(
                modifier = Modifier.padding(16.dp),
                containerColor = MaterialTheme.colorScheme.primary,
                contentColor = MaterialTheme.colorScheme.onPrimary,
                actionColor = MaterialTheme.colorScheme.secondary,
                action = {
                    snackbarData.actionLabel?.let { actionLabel ->
                        TextButton(onClick = { snackbarData.performAction() }) {
                            Text(actionLabel)
                        }
                    }
                }
            ) {
                Text(snackbarData.message)
            }
        }
    )
}

@Composable
fun CustomSnackbarExample() {
    val snackbarHostState = remember { SnackbarHostState() }
    val scope = rememberCoroutineScope()

    Scaffold(
        snackbarHost = { CustomSnackbar(snackbarHostState) },
        topBar = {
            TopAppBar(
                title = { Text("Custom Snackbar Example") }
            )
        },
        content = { innerPadding ->
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(innerPadding),
                contentAlignment = Alignment.Center
            ) {
                Button(onClick = {
                    scope.launch {
                        snackbarHostState.showSnackbar(
                            message = "This is a custom Snackbar",
                            actionLabel = "Dismiss",
                            duration = SnackbarDuration.Short
                        )
                    }
                }) {
                    Text("Show Custom Snackbar")
                }
            }
        }
    )
}

@Preview(showBackground = true)
@Composable
fun CustomSnackbarExamplePreview() {
    CustomSnackbarExample()
}

解释

  1. 自定义 Snackbar:

    • 定义一个 CustomSnackbar 组件,使用 SnackbarHost 并自定义 snackbar 参数来修改 Snackbar 的外观。
    • 自定义参数包括 modifiercontainerColorcontentColoractionColor
  2. 使用自定义 Snackbar:

    • ScaffoldsnackbarHost 参数中使用 CustomSnackbar,替代默认的 SnackbarHost

通过上述示例和解释,你可以在 Jetpack Compose 中灵活使用和自定义 Snackbar,以提供更好的用户体验。