如何将可复用ExtendedFloatingActionButton与可复用Scaffold关联
解决Jetpack Compose复用Scaffold中ExtendedFAB随滚动展开/收起的问题
你的核心问题是列表的LazyListState和FAB没有共享——当前MyLazyColumn内部创建的listState是局部变量,外部的FAB根本拿不到,所以滚动事件无法同步到FAB的expanded状态;同时MyHomeScreen里传递FAB时直接传LazyListState?是无效的,没有关联到实际的列表状态。
解决方案步骤
- 让
MyLazyColumn接收外部传入的LazyListState,而非内部创建 - 在页面级组件(
MyHomeScreen)中创建共享的LazyListState实例,同时传给列表和FAB - 修正
MyHomeScreen中FAB的调用方式,传递正确的listState实例
修改后的完整代码
@Composable fun MyReusableScaffold( scaffoldTitle: String, scaffoldFab: @Composable () -> Unit, scaffoldContent: @Composable (contentPadding: PaddingValues) -> Unit ) { Scaffold( topBar = { LargeTopAppBar(title = { Text(text = scaffoldTitle) }) }, floatingActionButton = scaffoldFab, content = { contentPadding -> scaffoldContent(contentPadding = contentPadding) } ) } @Composable fun MyFAB(listState: LazyListState) { ExtendedFloatingActionButton( text = { Text(text = "title") }, icon = { Icon(Icons.Filled.Add, contentDescription = "Add") }, expanded = listState.isScrollingUp(), onClick = { /* 处理点击事件 */ } ) } // 实现滚动方向判断的扩展函数 @OptIn(ExperimentalFoundationApi::class) fun LazyListState.isScrollingUp(): Boolean { return this.firstVisibleItemScrollDirection == ScrollDirection.Up } @Composable fun <T> MyLazyColumn( modifier: Modifier = Modifier, listState: LazyListState, // 改为接收外部状态 items: List<T>, itemContent: @Composable (T) -> Unit ) { LazyColumn( modifier = modifier, state = listState ) { items(items) { item -> itemContent(item) } } } @Composable fun MyHomeScreen() { // 在页面层级创建共享的LazyListState,确保列表和FAB用同一个状态 val listState = rememberLazyListState() MyReusableScaffold( scaffoldTitle = "title", scaffoldFab = { MyFAB(listState = listState) }, // 传递共享状态 scaffoldContent = { contentPadding -> MyHomeScreenContent(contentPadding = contentPadding, listState = listState) } ) } @Composable fun MyHomeScreenContent( modifier: Modifier = Modifier, contentPadding: PaddingValues = PaddingValues(), listState: LazyListState ) { // 示例数据 val demoItems = List(50) { "Item $it" } MyLazyColumn( modifier = modifier.padding(contentPadding), listState = listState, items = demoItems ) { item -> Text( text = item, modifier = Modifier .fillMaxWidth() .padding(16.dp) ) } }
关键说明
- 状态共享:把
LazyListState的创建提到MyHomeScreen层级,让列表和FAB共用同一个状态实例,滚动事件的状态才能同步到FAB。 - 组件复用性:
MyLazyColumn改为接收外部状态,保持了复用能力——不同页面可以传入自己的listState,也能灵活和其他组件共享状态。 - 滚动判断逻辑:确保
isScrollingUp()扩展函数正确实现,通过滚动方向控制FAB的展开/收起。
内容的提问来源于stack exchange,提问作者wbk727
相关产品推荐
相关产品推荐

