如何创建含多组嵌套列表、可整体滚动的SwiftUI侧边栏?
解决SwiftUI侧边栏DisclosureGroup嵌套列表的滚动与展开问题
问题描述
我想要创建一个包含多个DisclosureGroup的侧边栏,其中部分DisclosureGroup包含嵌套列表。侧边栏完全展开后长度会超过屏幕,因此需要支持整体滚动。
当前代码存在以下问题:
- Section 2可正常展开,但Section 1完全无法展开;
- 给Section 3设置固定frame可显示嵌套列表,但会出现滚动嵌套的情况,且frame无法随展开的嵌套列表自适应调整。
目标是实现一个包含三个DisclosureGroup的侧边栏,支持折叠、展开并作为整体单元滚动。
问题代码
import SwiftUI class MenuItem: Identifiable { var id = UUID() var text : String var children : [MenuItem]? = [MenuItem]() init(text: String) { self.text = text } } struct ContentView: View { var menuItems = [MenuItem]() init() { for itemText in ["One", "Two", "Three", "Four", "Five"] { menuItems.append(MenuItem(text: itemText)) } for item in menuItems { for childText in ["A", "B", "C", "D", "E"] { item.children?.append(MenuItem(text: childText)) } } } var body: some View { ScrollView { DisclosureGroup("Section 1") { List(menuItems, children: \.children) { item in Text(item.text) } } DisclosureGroup("Section 2") { Text("Some other stuff") } DisclosureGroup("Section 3") { List(menuItems, children: \.children) { item in Text(item.text) }.frame(minHeight: 300) } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
解决方案
问题核心在于List自带滚动特性,与外层ScrollView产生冲突,且默认会占满可用空间,导致DisclosureGroup无法正确计算展开高度。改用OutlineGroup替代List即可解决——它专门用于展示层级数据,无内置滚动,能完美适配DisclosureGroup的折叠展开逻辑,配合外层ScrollView实现整体滚动。
修改后的代码如下:
import SwiftUI class MenuItem: Identifiable { var id = UUID() var text : String var children : [MenuItem]? = [MenuItem]() init(text: String) { self.text = text } } struct ContentView: View { var menuItems = [MenuItem]() init() { for itemText in ["One", "Two", "Three", "Four", "Five"] { menuItems.append(MenuItem(text: itemText)) } for item in menuItems { for childText in ["A", "B", "C", "D", "E"] { item.children?.append(MenuItem(text: childText)) } } } var body: some View { ScrollView { VStack(alignment: .leading, spacing: 0) { DisclosureGroup("Section 1") { OutlineGroup(menuItems, children: \.children) { item in Text(item.text) .padding(.vertical, 8) .padding(.leading, 20) } } .padding(.vertical, 4) DisclosureGroup("Section 2") { Text("Some other stuff") .padding(.vertical, 8) .padding(.leading, 20) } .padding(.vertical, 4) DisclosureGroup("Section 3") { OutlineGroup(menuItems, children: \.children) { item in Text(item.text) .padding(.vertical, 8) .padding(.leading, 20) } } .padding(.vertical, 4) } .padding() } .frame(width: 250) // 侧边栏固定宽度,可按需调整 } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
关键修改点
- 替换
List为OutlineGroup:OutlineGroup仅负责渲染层级结构,无内置滚动,能跟随DisclosureGroup的展开自动调整高度; - 添加内边距:给列表项和DisclosureGroup设置合适内边距,模拟原生List的视觉体验;
- 用
VStack统一包裹:让所有DisclosureGroup垂直排列,确保外层ScrollView能将整个侧边栏作为单一滚动单元。
修改后所有DisclosureGroup均可正常折叠展开,侧边栏整体滚动流畅,嵌套列表高度会自动适配内容,无滚动嵌套问题。
内容的提问来源于stack exchange,提问作者Ductcoder
相关产品推荐
相关产品推荐

