当前位置: 首页 > backend >正文

Compose笔记(四十七)--SnackbarHost

           这一节主要了解一下Compose中的SnackbarHost,在Jetpack Compose开发中,SnackbarHost是管理Snackbar显示的核心组件,通常与Scaffold结合使用,提供统一的底部消息提示区域。

API
SnackbarHost组件,是一个容器组件,用于在界面中指定Snackbar的显示位置,并将Snackbar与SnackbarHostState关联,使其能够响应状态变化。
构造函数关键参数:
hostState:必填,类型为SnackbarHostState,用于控制Snackbar的显示状态。
modifier:可选,用于设置布局样式。
snackbar:可选,用于自定义Snackbar的样式。
SnackbarHostState状态类,管理Snackbar的状态数据,包括当前显示的Snackbar内容、交互结果等
核心属性和方法:
currentSnackbarData:当前显示的Snackbar数据。
showSnackbar():挂起函数,用于触发Snackbar显示,返回SnackbarResult。
currentSnackbarData?.dismiss():关闭当前显示的Snackbar。

场景:
1 轻量级操作结果提示,如:删除数据后提示 “已删除”、保存设置后提示 “保存成功”等。
2 带交互的二次操作,通过actionLabel添加动作按钮,支持用户执行撤销、重试等操作。
3 长时间提示与手动关闭,使用SnackbarDuration.Indefinite设置无限期显示,配合手动关闭按钮
4 自定义样式适配主题,通过SnackbarHost的snackbar参数自定义外观,如修改背景色、文本大小等,适配应用主题。

栗子:

implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
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.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel  
import kotlinx.coroutines.launchclass DeleteViewModel : ViewModel() {var items by mutableStateOf(listOf("项目1", "项目2", "项目3"))private setfun deleteLastItem() {if (items.isNotEmpty()) {items = items.dropLast(1)}}fun undoDelete(deletedItem: String) {items = items + deletedItem}
}@Composable
fun SnackbarExample(viewModel: DeleteViewModel = viewModel()
) {val snackbarHostState = remember { SnackbarHostState() }val scope = rememberCoroutineScope()var lastDeletedItem by remember { mutableStateOf("") }Scaffold(snackbarHost = { SnackbarHost(snackbarHostState) },topBar = {Text(text = "Snackbar示例",modifier = Modifier.padding(20.dp))}) { innerPadding ->Column(modifier = Modifier.fillMaxSize().padding(innerPadding).padding(20.dp),horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.Center) {Text(text = "当前项目: ${viewModel.items.joinToString()}",modifier = Modifier.padding(bottom = 30.dp))Button(onClick = {if (viewModel.items.isNotEmpty()) {lastDeletedItem = viewModel.items.last()viewModel.deleteLastItem()scope.launch {val result = snackbarHostState.showSnackbar(message = "已删除 '$lastDeletedItem'",actionLabel = "撤销",duration = androidx.compose.material3.SnackbarDuration.Short)if (result == androidx.compose.material3.SnackbarResult.ActionPerformed) {viewModel.undoDelete(lastDeletedItem)}}} else {scope.launch {snackbarHostState.showSnackbar(message = "没有可删除的项目",duration = androidx.compose.material3.SnackbarDuration.Short)}}}) {Icon(imageVector = Icons.Default.Delete,contentDescription = "删除",modifier = Modifier.padding(end = 8.dp))Text("删除最后一项")}}}
}
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.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch@Composable
fun SnackbarExample() {val snackbarHostState = remember { SnackbarHostState() }val scope = rememberCoroutineScope()var inputText by remember { mutableStateOf("") }Scaffold(snackbarHost = {SnackbarHost(snackbarHostState) { data ->Snackbar(action = {if (data.visuals.actionLabel != null) {Button(onClick = { data.performAction() }) {Text(data.visuals.actionLabel ?: "")}}}) {Text(data.visuals.message)}}},topBar = {Text(text = "Snackbar Demo",modifier = Modifier.padding(20.dp))}) { innerPadding ->Column(modifier = Modifier.fillMaxSize().padding(innerPadding).padding(20.dp),horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.CenterVertically)) {OutlinedTextField(value = inputText,onValueChange = { inputText = it },label = { Text("请输入内容") },keyboardOptions = KeyboardOptions(imeAction = ImeAction.Send),keyboardActions = KeyboardActions(onSend = {submitInput(inputText, snackbarHostState, scope)}))Button(onClick = { submitInput(inputText, snackbarHostState, scope) }) {Text("提交")}Button(onClick = {scope.launch {snackbarHostState.currentSnackbarData?.dismiss()}},enabled = snackbarHostState.currentSnackbarData != null) {Text("关闭当前提示")}}}
}private fun submitInput(text: String,snackbarHostState: SnackbarHostState,scope: kotlinx.coroutines.CoroutineScope
) {scope.launch {if (text.isBlank()) {snackbarHostState.showSnackbar(message = "错误:输入不能为空!",duration = androidx.compose.material3.SnackbarDuration.Short)} else {snackbarHostState.showSnackbar(message = "成功:已提交内容 '$text'",actionLabel = "知道了",duration = androidx.compose.material3.SnackbarDuration.Long)}}
}

注意:
1 必须与Scaffold配合使用,SnackbarHost通常作为Scaffold的snackbarHost参数传入,确保Snackbar显示在正确的层级。
2 挂起函数需在协程中调用,showSnackbar()和dismiss()是挂起函数,必须在协程作用域中调用,否则会编译报错。
3 显示时长控制,避免长时间显示,除非提供明确的关闭方式。

http://www.xdnf.cn/news/18540.html

相关文章:

  • Axure:有个特别实用的功能
  • 什么是AI宠物
  • [2025CVPR-目标检测方向]PointSR:用于无人机视图物体检测的自正则化点监控
  • C++的struct里面可以放函数,讨论一下C++和C关于struct的使用区别
  • leetcode算法刷题的第十六天
  • 力扣热题之技巧
  • 雷卯针对香橙派Orange Pi 3G-IoT-B开发板防雷防静电方案
  • 云原生、容器及数据中心网络相关名词记录
  • 无人机光伏巡检误检率↓79%!陌讯多模态融合算法在组件缺陷检测的落地优化
  • 为什么存入数据库的中文会变成乱码
  • 浙江龙庭翔新型建筑材料有限公司全屋定制:畅享品质生活新境界!
  • 【小沐学GIS】基于C++绘制三维数字地球Earth(osgEarth、三维瓦片地球)第十期
  • 如何使用和优化SQL Server存储过程:全面指南
  • PETR/PETRv2
  • 从 M4S 到 MP4:用 FFmpeg 轻松合并音视频文件
  • C++矩阵类设计与实现:高效、健壮的线性代数工具
  • 2025年音乐创作大模型有哪些?国内国外模型汇总以及优点分析
  • 5G物联网的现实与未来:CTO视角下的成本、风险与破局点
  • Stm32通过ESP8266 WiFi连接阿里云平台
  • Spring Boot 校验分组(Validation Groups)高级用法全指南
  • 从0到1:数据库进阶之路,解锁SQL与架构的奥秘
  • 32位内部数据通路是什么?
  • 基于llama.cpp的量化版reranker模型调用示例
  • 【golang】制作linux环境+golang的Dockerfile | 如何下载golang镜像源
  • 避开MES实施的“坑”:详解需求、开发、上线决胜点
  • openharmony之启动恢复子系统详解
  • Doxygen是什么?
  • Neural Network with Softmax output|神经网络的Softmax输出
  • 深入剖析Spring Boot应用启动全流程
  • 第七章 利用Direct3D绘制几何体