SwiftUI可变高度子视图列表占用额外空间问题求助
问题原因
SwiftUI的List底层依赖UIKit的UITableView实现,它会缓存单元格的高度来优化性能。当你展开Collapsible视图并添加item后,List会记录此时该单元格的高度;即使后续通过frame(maxHeight: 0)折叠视图,List的高度缓存并未同步更新——因为被折叠的视图只是被裁剪,其内部的VStack依然存在,视图的**固有内容尺寸(intrinsic content size)**还是保留了添加item后的高度,导致List依旧为该单元格预留空间。
解决方法
有两种可靠的解决思路,根据需求选择:
思路1:条件渲染折叠内容
直接在折叠状态下不渲染内部的VStack,彻底移除这部分视图的固有尺寸,让List能正确计算单元格高度。
修改Collapsible的代码:
struct Collapsible: View { @State private var isExpanded: Bool = false @State private var items: [String] = ["item1", "item2", "item3"] var body: some View { VStack { HStack { Text("Tap Me") Spacer() Text("Info") } .contentShape(Rectangle()) .onTapGesture { isExpanded.toggle() } // 只有展开时才渲染内容 if isExpanded { VStack { ForEach(items, id: \.self) { item in HStack { Text("Item") Spacer() Text("Info") } .padding(.vertical, 5) } Button("Add Item") { items.append("new item") } } } } .background(Color.cyan) } }
思路2:强制List刷新单元格高度
通过给Collapsible视图添加动态ID,让List在折叠状态或items数量变化时,重新创建单元格并计算高度。
修改Collapsible的代码:
struct Collapsible: View { @State private var isExpanded: Bool = false @State private var items: [String] = ["item1", "item2", "item3"] var body: some View { VStack { HStack { Text("Tap Me") Spacer() Text("Info") } .contentShape(Rectangle()) .onTapGesture { isExpanded.toggle() } VStack { ForEach(items, id: \.self) { item in HStack { Text("Item") Spacer() Text("Info") } .padding(.vertical, 5) } Button("Add Item") { items.append("new item") } } .frame(maxHeight: isExpanded ? .none : 0) .clipped() } .background(Color.cyan) // 根据状态生成动态ID,触发List重新计算高度 .id("\(isExpanded)-\(items.count)") } }
内容的提问来源于stack exchange,提问作者Nicolas Gimelli
相关产品推荐
相关产品推荐

