如何在Jetpack Compose的MD3 Scaffold中显示Snackbar
Jetpack Compose Material 3 中Scaffold实现Snackbar方案
Material 3 对Scaffold的状态管理逻辑做了拆分重构,直接移除了MD2版本里统一封装的ScaffoldState,所以找不到rememberScaffoldState()方法属于正常情况,不是导包错误。MD3下Snackbar的实现不需要依赖ScaffoldState,单独管理状态挂载即可,步骤如下:
- 第一步:在Composable中单独初始化Snackbar所需状态
不再需要从ScaffoldState中获取SnackbarHostState,直接创建实例即可,同时准备协程作用域用来触发展示逻辑:import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @Composable fun Md3Screen() { // 持有Snackbar宿主状态 val snackbarHostState = remember { SnackbarHostState() } // 用来调用挂起方法showSnackbar的协程作用域 val scope = rememberCoroutineScope() } - 第二步:将状态挂载到MD3 Scaffold上
MD3的Scaffold开放了snackbarHost参数,需要传入自定义的SnackbarHost可组合项,把刚才创建的状态实例传进去,否则无法拿到Scaffold内置SnackbarHost的引用,自然没法触发弹出:import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarResult import androidx.compose.material3.SnackbarDuration import androidx.compose.material3.Text import androidx.compose.ui.Modifier import kotlinx.coroutines.launch @Composable fun Md3Screen() { val snackbarHostState = remember { SnackbarHostState() } val scope = rememberCoroutineScope() Scaffold( // 绑定SnackbarHost和对应状态 snackbarHost = { SnackbarHost(hostState = snackbarHostState) } ) { contentPadding -> Box( modifier = Modifier .fillMaxSize() .padding(contentPadding) ) { Button(onClick = { scope.launch { // 调用方式和MD2完全一致 val result = snackbarHostState.showSnackbar( message = "Snackbar测试内容", actionLabel = "关闭", duration = SnackbarDuration.Short ) // 同样可以获取点击结果 when(result) { SnackbarResult.ActionPerformed -> { /* 点击了操作按钮 */ } SnackbarResult.Dismissed -> { /* Snackbar自动消失/手动划走 */ } } } }) { Text("点击弹出Snackbar") } } } }
踩坑提醒
- 所有相关组件请从
androidx.compose.material3包导入,不要和MD2的androidx.compose.material包下的同名类混用,否则会出现类型不匹配的编译错误 - MD3中Scaffold的其他交互状态(比如侧边抽屉状态)也采用了同样的拆分逻辑,不再统一封装在ScaffoldState中,都需要单独创建实例、单独挂载到Scaffold对应参数上
- 如果需要自定义Snackbar的样式,直接在传入的
SnackbarHost中自定义snackbar参数的内容即可,比MD2的自定义方式更灵活
内容的提问来源于stack exchange,提问作者Tonnie
相关产品推荐
相关产品推荐

