繁体   English   中英

Jetpack Compose 中未显示 Snackbar

[英]Snackbar not showing in Jetpack Compose

我的屏幕有一个按钮,点击它,我想在短时间内显示一个小吃栏。 所以这是我的可组合:

@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)
            }
        }
    )
}

这段代码有什么问题? 任何帮助,将不胜感激。

SnackbarHostStateScaffold中显示一个snackbar ,或者可以作为参数传递给SnackBar组合。

为什么小吃店主机不显示小吃店?

每当更改state时,snackBar 就没有任何ScaffoldSnackbarHost来显示内容。 snackbarHostState也可以在编写您已经完成的SnackBar时传递 -检查解决方案 2

无效state 期间,您既没有使用Scaffold ,也没有通过使用snackBarHostState组成SnackBarHost

解决方案 1

我们需要将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
         )
   }
}

1

解决方案2 : -

您永远不会在无效的 state 中编写RegisterLocation(locationVm, snackbarHostState) 根据代码,如果我们在 Invalid state 中组合RegisterLocation可组合项,那么作为组合项添加的小吃店也应该出现。

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 ,其中包含基于其 position 在屏幕中绘制的所有 UI 元素。 因此,在重新组合期间,它只比较并显示在重新组合期间绘制的 UI 元素,并删除在先前组合期间构建的其他redundant组件(如在重新组合期间我们不访问的 UI 组件中)成分被删除)。

对于您的情况:- states完全不同,我们在第二次合成期间从未访问过Init state。 因此,compose 在重新组合期间看到我们从未访问过Init state,因此它从 memory 中删除了Init UI。 (在引擎盖下使用positional memoisation )。

请检查compose under the hood

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM