You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现点击Card Composable内IconButton控制BottomSheetScaffold展开收起

解决BottomSheetScaffold点击Card内IconButton无法展开/收起的问题

你的代码核心问题是**Cards_SearchingClicking组件内部重新创建了独立的BottomSheetScaffoldState**,这个状态和外层BottomSheetScaffold使用的状态完全无关,所以点击IconButton时操作的是一个未关联到底部弹窗的状态,自然无法控制弹窗的展开/收起。

修改步骤:

  1. 将外层的scaffoldState和scope作为参数传递给Cards_SearchingClicking组件
  2. 删除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 09:25:43