如何实现点击Card Composable内IconButton控制BottomSheetScaffold展开收起
你的代码核心问题是**Cards_SearchingClicking组件内部重新创建了独立的BottomSheetScaffoldState**,这个状态和外层BottomSheetScaffold使用的状态完全无关,所以点击IconButton时操作的是一个未关联到底部弹窗的状态,自然无法控制弹窗的展开/收起。
修改步骤:
- 将外层的
scaffoldState和scope作为参数传递给Cards_SearchingClicking组件 - 删除
Cards_SearchingClicking内部创建的scope和scaffoldState实例
修改后的完整代码:
@OptIn(ExperimentalMaterialApi::class, ExperimentalCoroutinesApi::class) @Composable fun ddd( navController: NavController, viewModel: SearchingClickingViewModel ) { val scope = rememberCoroutineScope() val scaffoldState = rememberBottomSheetScaffoldState() BottomSheetScaffold( scaffoldState = scaffoldState, sheetPeekHeight = 10.dp, sheetContent = { Box( Modifier .fillMaxWidth() .height(128.dp), contentAlignment = Alignment.Center ) { Text("Swipe up to expand sheet") } Column( Modifier .fillMaxWidth() .padding(64.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text("Sheet content") Spacer(Modifier.height(20.dp)) Button( onClick = { scope.launch { scaffoldState.bottomSheetState.collapse() } } ) { Text("Click to collapse sheet") } } }, topBar = { TopAppBar( title = { Text(text = "All Calling Customers") }, navigationIcon = { IconButton(onClick = { navController.navigate(Screen.Home.route) { popUpTo(Screen.Home.route) { inclusive = true } } }) { Icon(Icons.Filled.ArrowBack, "backIcon") } }, backgroundColor = MaterialTheme.colors.primary, contentColor = MaterialTheme.colors.primary, elevation = 0.dp ) }, drawerContent = { Column( Modifier .fillMaxWidth() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text("Drawer content") Spacer(Modifier.height(20.dp)) Button(onClick = { scope.launch { scaffoldState.drawerState.close() } }) { Text("Click to close drawer") } } } ) { LazyColumn( contentPadding = PaddingValues( horizontal = 0.dp, vertical = 0.dp ), verticalArrangement = Arrangement.spacedBy(10.dp) ) { items(100) { // 传递scope和scaffoldState给子组件 Cards_SearchingClicking( data = it!!, navController = navController, scaffoldState = scaffoldState, scope = scope ) } } } } @OptIn(ExperimentalMaterialApi::class) @Composable fun Cards_SearchingClicking( data: SearchingClickingItems, navController: NavController, // 添加参数接收外层的状态和协程作用域 scaffoldState: BottomSheetScaffoldState, scope: CoroutineScope ) { val context = LocalContext.current // 移除内部的scope和scaffoldState创建 Card( modifier = Modifier .fillMaxSize(), shape = RoundedCornerShape(0.dp), elevation = 1.dp ) { Column( modifier = Modifier .fillMaxSize() .padding(20.dp) ) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier .fillMaxWidth() ) { IconButton( onClick = { scope.launch { // 直接操作外层传递进来的scaffoldState if (scaffoldState.bottomSheetState.isCollapsed) { scaffoldState.bottomSheetState.expand() } else { scaffoldState.bottomSheetState.collapse() } } }, modifier = Modifier .size(35.dp) ) { Icon( Icons.Filled.MoreVert, contentDescription = null ) } } } } //END Card }
额外说明:
- 确保所有控制
BottomSheetScaffold的操作都使用同一个BottomSheetScaffoldState实例,这是Compose状态管理的核心原则之一:状态提升,将状态放在需要共享的最高层级,然后向下传递。 - 如果你有多个组件需要控制底部弹窗,也可以考虑将状态放在ViewModel中,通过ViewModel来统一管理,这样更适合复杂场景。
内容的提问来源于stack exchange,提问作者Mohammed
相关产品推荐
相关产品推荐

