英文:
Jetpack compose bottom sheet drawer opens on its own
问题
我有以下的Compose组件:
@Composable
fun ProductDetails(viewModel: ProductDetailsViewModel) {
val productInstalmentsByOcrName by viewModel.productInstalmentsByOcrName.collectAsStateWithLifecycle()
val product by viewModel.product.collectAsStateWithLifecycle()
val scope = rememberCoroutineScope()
val drawerState = rememberBottomDrawerState(BottomDrawerValue.Closed)
BottomDrawer(
drawerState = drawerState,
drawerContent = {
ReportModalContent(ocrProductNames = productInstalmentsByOcrName?.map { it.first }
?: emptyList(), onReport = { ocrProductName ->
viewModel.onReport(ocrProductName)
scope.launch {
drawerState.close()
}
})
},
) {
// .... 其余的代码...
IconButton(
onClick = { scope.launch { drawerState.open() } },
modifier = Modifier.align(Alignment.TopEnd)
) {
// ... 其余的代码
这个组件代表了我的应用程序中的一个屏幕。当我导航到它时,在Composable的第一个渲染中,抽屉关闭,drawerState.isOpen == false
。但是立刻之后,没有用户按下应该打开抽屉的按钮,Composable重新渲染并自动打开了抽屉。
在这段代码中,我没有在任何其他地方访问drawerState
。
我认为这可能与导航组件有关,因为这个组件代表一个屏幕,但不是初始屏幕。但即使作为初始目标渲染,抽屉也会自动打开。
第一个目标屏幕也有一个看起来完全相同的BottomDrawer,所以我认为这可能会有某种干扰。但是即使在其他组件的相关代码中注释掉底部抽屉的代码,问题仍然存在。
由于另一个组件有一个看起来相同的BottomDrawer,我不知道这一个有什么问题。
我该如何解决这个问题?
以下是导航Compose部分。产品列表只是一个单元格列表,单击其中一个单元格会导航到产品详细信息组件。身份验证屏幕与我的问题无关。在进行此问题的测试时,我已经登录,所以我不与AuthScreen互动。
文件 NavigationComposable.kt
fun Navigation(viewModel: NavigationViewModel = koinViewModel()) {
val navController = rememberNavController()
val startDestination by viewModel.startRoute.collectAsStateWithLifecycle()
NavHost(navController = navController, startDestination = startDestination) {
composable(Routes.AUTH) {
AuthScreen(navController = navController)
}
composable(Routes.PRODUCT_LIST) {
ProductList(navController = navController)
}
composable(
Routes.PRODUCT_DETAILS,
arguments = listOf(navArgument(Routes.PRODUCT_ID_ARG) { type = NavType.IntType })
)
{
val productId = it.arguments?.getInt(Routes.PRODUCT_ID_ARG)
ProductDetails(viewModel = getViewModel { parametersOf(productId) })
}
}
}
文件 NavigationViewModel.kt
class NavigationViewModel(authRepository: AuthRepository) : ViewModel() {
val startRoute = authRepository.isLoggedIn.map {
if (it) Routes.PRODUCT_LIST else Routes.AUTH
}.stateIn(viewModelScope, SharingStarted.Eagerly, Routes.AUTH)
}
希望这能帮助您解决问题。
英文:
I have the following compose component:
@Composable
fun ProductDetails(viewModel: ProductDetailsViewModel) {
val productInstalmentsByOcrName by viewModel.productInstalmentsByOcrName.collectAsStateWithLifecycle()
val product by viewModel.product.collectAsStateWithLifecycle()
val scope = rememberCoroutineScope()
val drawerState = rememberBottomDrawerState(BottomDrawerValue.Closed)
BottomDrawer(
drawerState = drawerState,
drawerContent = {
ReportModalContent(ocrProductNames = productInstalmentsByOcrName?.map { it.first }
?: emptyList(), onReport = { ocrProductName ->
viewModel.onReport(ocrProductName)
scope.launch {
drawerState.close()
}
})
},
) {
// .... The rest of the code...
IconButton(
onClick = { scope.launch { drawerState.open() } },
modifier = Modifier.align(Alignment.TopEnd)
) {
// ... The rest of the code
This composable represents a screen in my app. When I navigate to it, in the first render of the Composable, the drawer is closed, with drawerState.isOpen == false
. But immediately after, without the user pressing on the button that should open the drawer, the Composable re-renders and the drawer opens on its own.
At no other point do I access drawerState
in this code.
I assumed it had something to do with the Navigation component, since this component represents a screen, but not the initial one. But even when rendering as initial destination, the drawer opens on its own.
The first destination screen also has a BottomDrawer that looks just like this, so I thought that might somehow interfere. But after commenting the code from the other component regarding, the bottom sheet the problem still persisted.
Since the other component has an identical looking BottomDrawer, I don't know what the problem with this one is.
How can I fix this?
Here is the navigation composable. The product list is just a list of cells, when tapping on one it navigates to the product details composable. The authentication screen is not relevant for my problem.
When I test for this problem, I am already logged in, so I don't interact with the AuthScreen
File NavigationComposable.kt
fun Navigation(viewModel: NavigationViewModel = koinViewModel()) {
val navController = rememberNavController()
val startDestination by viewModel.startRoute.collectAsStateWithLifecycle()
NavHost(navController = navController, startDestination = startDestination) {
composable(Routes.AUTH) {
AuthScreen(navController = navController)
}
composable(Routes.PRODUCT_LIST) {
ProductList(navController = navController)
}
composable(
Routes.PRODUCT_DETAILS,
arguments = listOf(navArgument(Routes.PRODUCT_ID_ARG) { type = NavType.IntType })
)
{
val productId = it.arguments?.getInt(Routes.PRODUCT_ID_ARG)
ProductDetails(viewModel = getViewModel { parametersOf(productId) })
}
}
}
File NavigationViewModel.kt
class NavigationViewModel(authRepository: AuthRepository) : ViewModel() {
val startRoute =authRepository.isLoggedIn.map {
if (it) Routes.PRODUCT_LIST else Routes.AUTH
}.stateIn(viewModelScope, SharingStarted.Eagerly, Routes.AUTH)
}
答案1
得分: 1
我找到了问题。在GitHub上阅读时,我遇到了这个。
看起来,如果BottomDrawer的内容为空(对我来说最初是这样)或者没有定位,那么BottomDrawer就会出现我描述的问题,它会自己打开。
英文:
I found the problem. Reading on GitHub, I came across this.
It seems if the content of the BottomDrawer is null (and initially for me it was) or otherwise unpositioned, the BottomDrawer experiences the issue I describe where it opens on its own.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论