如何在Jetpack Compose中实现自定义Toast?
Jetpack Compose 自定义Toast实现方案
方案1:封装原生Toast实现自定义样式
该方案兼容系统Toast的全局显示逻辑,不需要依赖当前Compose页面的生命周期,适合需要跨页面显示的场景。
实现代码如下:
fun Context.showCustomToast( message: String, duration: Int = Toast.LENGTH_SHORT, icon: Int? = null ) { val toast = Toast.makeText(this, "", duration) // 用ComposeView渲染自定义样式,无需编写xml布局 val composeView = ComposeView(this).apply { setContent { Surface( shape = RoundedCornerShape(8.dp), color = Color(0xCC000000), shadowElevation = 4.dp ) { Row( modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { icon?.let { Icon( painter = painterResource(id = it), contentDescription = null, tint = Color.White, modifier = Modifier.size(20.dp) ) } Text( text = message, color = Color.White, fontSize = 14.sp ) } } } } toast.view = composeView // 自定义Toast显示位置,距离底部120dp toast.setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 120.dp.roundToPx()) toast.show() }
在Composable中调用方式:
val context = LocalContext.current Button(onClick = { context.showCustomToast( message = "操作成功", icon = R.drawable.ic_success, duration = Toast.LENGTH_SHORT ) }) { Text("显示Toast") }
注意事项:
- Android 11及以上系统禁止了自定义Toast的后台显示,仅前台显示不受影响
- 若需要适配更高版本系统限制,推荐使用第二种纯Compose实现方案
方案2:纯Compose实现的页面内自定义Toast
该方案完全运行在Compose树内,不受系统版本限制,样式自定义自由度更高,可以实现动画、手势交互等复杂效果。
实现思路:用CompositionLocal提供全局的Toast触发方法,在根布局嵌套Toast悬浮层,通过状态控制显示隐藏。
步骤1:定义Toast数据类和状态控制器
data class ToastState( val message: String, val duration: Long = 2000L, val icon: Int? = null ) class ToastHostState : androidx.compose.runtime.SaveableStateHolder { val currentToast = mutableStateOf<ToastState?>(null) private var toastJob: Job? = null fun showToast(toast: ToastState) { toastJob?.cancel() currentToast.value = toast toastJob = CoroutineScope(Dispatchers.Main).launch { delay(toast.duration) currentToast.value = null } } override fun saveState(): Bundle? = null override fun restoreState(savedState: Bundle?) = Unit override fun <T : Any> removeState(key: Any) = Unit override fun <T : Any> consumeSavedState(key: Any): T? = null }
步骤2:定义CompositionLocal传递全局状态
val LocalToastHostState = staticCompositionLocalOf<ToastHostState> { error("No ToastHostState provided, please init at root layout") }
步骤3:实现ToastHost悬浮层组件
@Composable fun ToastHost( hostState: ToastHostState, modifier: Modifier = Modifier ) { val toast = hostState.currentToast.value // 自带显隐动画 AnimatedVisibility( visible = toast != null, modifier = modifier.fillMaxSize(), enter = fadeIn() + slideInVertically(initialOffsetY = { it / 2 }), exit = fadeOut() + slideOutVertically(targetOffsetY = { it / 2 }) ) { toast?.let { Box( modifier = Modifier .fillMaxSize() .padding(bottom = 120.dp), contentAlignment = Alignment.BottomCenter ) { Surface( shape = RoundedCornerShape(8.dp), color = Color(0xCC000000), shadowElevation = 4.dp ) { Row( modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { toast.icon?.let { iconRes -> Icon( painter = painterResource(id = iconRes), contentDescription = null, tint = Color.White, modifier = Modifier.size(20.dp) ) } Text( text = toast.message, color = Color.White, fontSize = 14.sp ) } } } } } }
步骤4:根布局注入全局状态
class MainActivity : ComponentActivity() { private val toastHostState = ToastHostState() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CompositionLocalProvider(LocalToastHostState provides toastHostState) { YourAppTheme { Box(modifier = Modifier.fillMaxSize()) { // 应用主内容,比如NavHost AppNavGraph() // Toast层放在最上层,保证不被其他内容遮挡 ToastHost(hostState = toastHostState) } } } } } }
步骤5:任意子Composable中调用
val toastHostState = LocalToastHostState.current Button(onClick = { toastHostState.showToast( ToastState( message = "纯Compose Toast测试", icon = R.drawable.ic_tip, duration = 3000L ) ) }) { Text("显示自定义Toast") }
注意事项:
- 该方案的Toast仅在当前Compose树内显示,退出当前页面会自动消失
- 可根据需求自定义动画、位置、交互逻辑,比如支持点击关闭、上滑消失等效果
内容的提问来源于stack exchange,提问作者ABINASH KUMAR
相关产品推荐
相关产品推荐

