我的屏幕有一个按钮,点击它,我想在短时间内显示一个 snackbar 。所以这是我的可组合:
@Composable
fun RegisterLocation(
navController: NavController,
locationVm: LocationViewModel = LocationViewModel()
) {
val uiState = locationVm.locationState.collectAsState(LocationUiState.Init)
val snackbarHostState = remember { SnackbarHostState() }
when (uiState.value) {
is LocationUiState.Init -> RegisterLocation(locationVm, snackbarHostState)
is LocationUiState.Invalid -> {
LaunchedEffect(locationVm.locationState.value) {
snackbarHostState.showSnackbar(
"Failed Creating Location. Try Again!!!"
)
}
}
is LocationUiState.Valid -> navController.popBackStack()
}
}
@Composable
fun RegisterLocation(locationVm: WLocationViewModel, snackbarHostState: SnackbarHostState) {
Box(Modifier.fillMaxSize()) {
Column {
SubmitLocation(locationVm)
}
Column(
Modifier
.fillMaxWidth()
.align(Alignment.BottomCenter)
) {
Text(text = "Hello") // <-- This is a dummy text and it shows in the UI. Moreover, it animates up to give space for snackbar. But the snackbar doesn't show up :(
RegistrationError(snackbarHostState)
}
}
}
@ExperimentalCoroutinesApi
@Composable
fun SubmitLocation(vm: WLocationViewModel) {
Button(
onClick = { vm.onCreate(LocationUiState.Invalid) },
modifier = Modifier.fillMaxWidth()
) {
Text(text = "Submit Location")
}
}
@Composable
fun RegistrationError(hostState: SnackbarHostState) {
SnackbarHost(
hostState = hostState,
modifier = Modifier.fillMaxWidth(),
snackbar = {
Snackbar {
Text(text = "Hello", color = Color.White)
}
}
)
}
这段代码有什么问题?任何帮助,将不胜感激。
最佳答案
SnackbarHostState
显示 snackbar
在 Scaffold
或者可以作为参数传递给 SnackBar
可组合的。
Why the snackbar host does not show the snackbar ?
每当
state
改变了snackBar 所做的不是 有任何Scaffold
或 SnackbarHost
显示内容。 (snackbarHostState
也可以在组成你已经完成的 SnackBar
时传递 - 检查解决方案 2 )您既没有使用
Scaffold
也不构成 SnackBarHost
通过使用 snackBarHostState
在期间无效 状态。解决方案一
我们需要附上
SnackbarHostState
在 Scaffold
让它出现。when (uiState.value) {
is LocationUiState.Init -> RegisterLocation(locationVm, snackbarHostState)
is LocationUiState.Invalid -> {
LaunchedEffect(locationVm.locationState.value) {
snackbarHostState.showSnackbar(
"Failed Creating Location. Try Again!!!",
"label",
duration = SnackbarDuration.Long
)
}
Scaffold(
// attach snackbar host state to the scaffold
scaffoldState = rememberScaffoldState(snackbarHostState = snackbarHostState),
content = { } // content is not mandatory
)
}
}
解决方案二 :-
你永远不会作曲
RegisterLocation(locationVm, snackbarHostState)
处于无效状态。根据代码,如果我们编写 RegisterLocation
在 Invalid 状态下可组合,然后应显示作为可组合添加的 snackbar 。when (uiState.value) {
is LocationUiState.Init -> RegisterLocation(locationVm, snackbarHostState)
is LocationUiState.Invalid -> {
RegistrationError(hostState = snackbarHostState)
LaunchedEffect(locationVm.locationState.value) {
snackbarHostState.showSnackbar(
"Failed Creating Location. Try Again!!!",
"label",
duration = SnackbarDuration.Long
)
}
}
}
更新 ( 详细说明 )Compose 维护一个
GroupArray
under the hood ,其中包含根据其位置在屏幕中绘制的所有 UI 元素。因此,在重新组合期间,它仅比较并显示在重新组合期间绘制的 UI 元素,并删除在先前组合期间构建的其他组件,即 redundant
。 (如在重新组合期间我们不访问的 UI 组件被删除)。对于您的情况:-
states
完全不同,我们从不访问Init
期间的状态第二作品。因此,compose 在重新组合期间看到我们从未访问过 Init
状态,因此它会删除 Init
内存中的 UI。(使用
positional memoisation
在引擎盖下)。请查看compose under the hood
关于android - Jetpack Compose 中未显示 Snackbar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67539655/