Skip to content

PopupPrompt — 轻提示 ​

全局单例的轻提示。不占布局,从顶部滑入,过一会儿自己走。

基本用法 ​

kotlin
PopupPrompt.success("已保存到相册")
PopupPrompt.error("复制失败")
PopupPrompt.warning("网络不稳定")
PopupPrompt.info("已复制到剪贴板")

长时间操作(必须自己收):

kotlin
PopupPrompt.loading("正在生成…")
generate(onDone = { PopupPrompt.dismiss() })

自定义时长 / 直接给类型:

kotlin
PopupPrompt.show("已加入队列", duration = 1500L)
PopupPrompt.show("稍后重试", type = PromptType.WARNING, duration = 6000L)

要读当前提示状态时(少见):

kotlin
val current by PopupPromptManager.promptState   // PromptData?,null 表示没有

参数 ​

PopupPrompt —— 对外入口(全是静态方法) ​

方法签名说明
success(message: String, duration: Long = 4000L)成功
error(message: String, duration: Long = 4000L)错误
info(message: String, duration: Long = 4000L)中性信息
warning(message: String, duration: Long = 4000L)警告
loading(message: String)加载中。不自动关闭,也传不了时长
dismiss()手动收掉当前提示
show(message: String, type: PromptType = PromptType.INFO, duration: Long = 4000L)要自定义类型或时长时用

PopupPromptManager ​

方法集与 PopupPrompt 完全一致(show / success / error / info / warning / loading / dismiss),另外多一个只读状态:

成员类型说明
promptStateState<PromptData?>当前提示,null 表示没有

日常用不到它 —— 只有要读当前状态时才需要。

PopupPrompt() —— 渲染容器 ​

@Composable fun PopupPrompt() 负责把当前提示画出来。HuaLuoTheme 内部已经挂了一次,通常不用调;只有自己搭主题、不经过 HuaLuoTheme 时才在界面根部手动挂一次。

PromptType / PromptData ​

PromptType图标说明
SUCCESSPhosphor.CheckCircle成功
ERRORPhosphor.XCircle错误
WARNINGPhosphor.Warning警告
INFOPhosphor.Info中性信息
LOADING波浪指示器加载中(不自动关闭)

PromptData(message: String, type: PromptType = PromptType.INFO, duration: Long = 4000L)

要点 ​

  • loading 必须自己 dismiss()。 它把 duration 设成 Long.MAX_VALUE 并且直接返回,不走自动关闭那条路 —— 忘了收就是一条永远挂在顶部的提示。
  • 同一时刻只有一个提示。 新的会顶掉旧的,不是排队。所以别用它承载需要逐条读的信息流。
  • PopupPrompt 和 PopupPromptManager 方法集一样,日常用前者即可。
  • 别自己造 Snackbar / Toast。 用这一套,位置、动效、语义色才是统一的。
  • duration 单位是毫秒,默认 4000。传太小(比如 300)会几乎看不见 —— 退出动画本身还要 300ms。
  • 别依赖「提示会挡住点击」:承载它的 Box 是全屏的,但里面只有提示本身那一块 Surface。它不拦截触摸,所以它下方的内容照常可点。

说明 ​

  • 为什么必须是反色底:浅色主题里 secondaryContainer 和页面背景几乎同色,提示飘上去等于「消失」。改用 inverseSurface 之后:白底页面 → 深色浮层,层级一眼可辨;深色主题下自动反转成浅色浮层,两态都成立。
  • 语义色也跟着一起反色,否则等于「深色图标压在深色底上」。这里曾经用过给与主题同向的表面准备的那组色:浅色主题的深色语义色压在反色后的深色底上几乎看不见,深色主题的浅色语义色压在浅色底上同样糊成一片 —— 「成功」和「错误」两个提示看起来都没颜色,就是「主题搞反了」的观感。M3 没有 inverseSuccess / inverseError 这类槽位,所以取各语义对应的容器槽位(inversePrimary / errorContainer / tertiaryContainer):容器色天生是「与所在主题表面反向」的柔和色,两边都成立。
  • 动效走 MaterialTheme.motionScheme 的 spatial 规格,而不是写死 tween(300) —— 提示是「会改变位置」的元素,正该用 spatial。滑入叠加 fadeIn(220),滑出叠加 fadeOut(180)。
  • 关闭时序:到时长后先播退出动画,再等 300ms 才真正清空状态。所以「上一条消失」和「下一条出现」之间是干净的。
  • 位置固定在顶部居中:padding(horizontal = 20.dp, vertical = 72.dp)、fillMaxWidth()、zIndex(1000f)。72dp 的上边距是为了避开状态栏和标题栏。
  • 形状是 AppShapes.cardSmall(16dp),shadowElevation = 0 —— 反色底已经足够表达层级,再加投影会显脏。
  • 命名变更:这一套原来叫 CustomToast / ToastManager / toastSuccess,现在全部收敛到 PopupPrompt + PopupPromptManager 两个对象上。旧名字在组件库里已经不存在,见到就是旧代码。
  • 连续 show 完全相同的内容(message / type / duration 三项全等)时状态不变,LaunchedEffect 不会重启 —— 也就是提示还在显示时再发一条一模一样的,不会重新计时。需要强制重建就传个不同的 duration。