如何在Jetpack Compose中点击Button时触发显示Snackbar
报错原因
你遇到的报错是因为onClick回调不属于@Composable上下文,所有带@Composable注解的函数只能在其他@Composable函数、或者Composable的生命周期作用域内调用,不能在普通的回调函数中直接构造Snackbar组件。
你编写的错误代码问题点:
Button(onClick = { Snackbar(action = {}) { Text("hello") } }
Snackbar是带@Composable注解的UI组件,不能在非Composable上下文的onClick回调中直接调用。
正确实现方案
Jetpack Compose中显示Snackbar需要依赖SnackbarHost和SnackbarHostState,通过状态驱动UI的方式控制Snackbar的显示,具体实现如下:
完整可运行代码
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column 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.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import kotlinx.coroutines.launch @Composable fun SnackbarDemoPage() { // 初始化Snackbar的宿主状态,用来控制Snackbar的显示、隐藏逻辑 val snackbarHostState = remember { SnackbarHostState() } // 获取和当前Composable生命周期绑定的协程作用域,用于调用挂起函数 val coroutineScope = rememberCoroutineScope() Scaffold( // 把SnackbarHost挂载到Scaffold的顶层,保证Snackbar可以正常浮在页面上层 snackbarHost = { SnackbarHost(hostState = snackbarHostState) } ) { innerPadding -> Column( modifier = Modifier .fillMaxSize() .padding(innerPadding), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Button(onClick = { // 在onClick回调中启动协程,触发Snackbar显示 coroutineScope.launch { snackbarHostState.showSnackbar( message = "hello", // 不需要操作按钮可删除actionLabel参数 actionLabel = "关闭" ) } }) { Text("点击显示Snackbar") } } } }
核心逻辑说明
- 如果你使用的是Material2组件库,只需要把所有
androidx.compose.material3的导入替换为androidx.compose.material即可,API逻辑完全一致 SnackbarHostState的showSnackbar是挂起函数,必须在协程中调用,rememberCoroutineScope创建的协程作用域会和当前页面生命周期绑定,页面销毁时自动取消协程,不会出现内存泄漏- 不需要使用Scaffold的场景也可以直接把
SnackbarHost放在页面布局的最顶层,效果和挂载到Scaffold一致
内容的提问来源于stack exchange,提问作者mike so
相关产品推荐
相关产品推荐

