在VStack嵌套可选项时保留SwiftUI List的选中状态
解决SwiftUI List嵌套容器后选中功能失效的问题
当List内部嵌套VStack这类容器时,List会把整个VStack识别为单个列表行,而非把内部ForEach的每个子项当作独立行,这就导致选中功能和键盘导航失效。可以通过以下两步解决:
- 给外层容器添加
.listRowInsets(EdgeInsets()),消除容器自带的行边距,让内部子项完全占据行空间 - 给每个可选中的子视图绑定
.tag(item),明确告诉List当前行对应的数据项
修改后的完整代码:
struct ContentView: View { @State private var selectedItem: Obj? @State var demoData: [Obj] = [.init("Bardi"), .init("John")] var body: some View { List(selection: $selectedItem) { VStack { ForEach(demoData, id: \.self) { item in Item(item: item) .tag(item) // 绑定选中标识 } } .listRowInsets(EdgeInsets()) // 重置行边距 } } } struct Obj: Hashable { var id: UUID = .init() var name: String = "" init(_ name: String) { self.name = name } } struct Item: View { var item: Obj var body: some View { VStack { Text(item.name) } } }
如果需要实现分类式列表,比如多个分组,可以给每个分类的外层容器添加标题,同时保持上述设置:
// 示例:多分类列表 List(selection: $selectedItem) { // 第一组 Section("分组1") { VStack { ForEach(group1Data, id: \.self) { item in Item(item: item) .tag(item) } } .listRowInsets(EdgeInsets()) } // 第二组 Section("分组2") { VStack { ForEach(group2Data, id: \.self) { item in Item(item: item) .tag(item) } } .listRowInsets(EdgeInsets()) } }
这样既保留了复杂的嵌套视图结构,又能让List正常处理选中状态和键盘导航。
内容的提问来源于stack exchange,提问作者Barrrdi
相关产品推荐
相关产品推荐

