You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 02:51:03