我试图找到一种方法来限制列表中可以选择的项目数量(使用EditMode),可以说我有一个包含6个项目的列表,并且希望用户能够选择其中3个项目,当选择3我想禁用未选择的人。但是,我希望所选的项目继续可取消选择,以便可以选择其他项目。 selectedItems集稍后会转换为数据模型并保存到数据库。
struct SelectItemListView: View {
var items = ["one", "two", "three", "four", "five", "six"]
var numberOfselectedItems = 3 // <- controlled by user input in real project
@State var selectedItems = Set<String>()
var body: some View {
List(items, id: \.self, selection: $selectedItems) { item in // <- id is \.id from datamodel in real project
Text(item)
}
.disabled(selectedItems.count >= numberOfselectedItems)
.environment(\.editMode, .constant(EditMode.active))
}
}
代码可以编译,但是会禁用整个列表,而不是单个行。在SwiftUI中甚至有可能吗?
答案 0 :(得分:0)
不幸的是,据我所知,目前还没有任何方法可以完成您想要的事情。
但是,可以通过创建自定义ListItemRow
来实现此目的,该自定义将接受任何内容(基本上是通用内容),但是它将选择和取消选择该行。
struct CustomListRow<Content> : View where Content : View {
@Binding var isSelectable: Bool
@State private var isSelected: Bool = false
var onSelectionChanged :(_ isSelected:Bool) -> () = {_ in}
var content: () -> Content
var body: some View {
HStack {
Circle()
.overlay(
Circle()
.stroke(self.isSelected ? Color.blue : Color(red: 0.741, green: 0.741, blue: 0.749), lineWidth: 1)
.overlay(Image(systemName: "checkmark").resizable().scaledToFit().frame(width: 12, height: 12).foregroundColor(Color.white))
)
.frame(width: 20, height: 20, alignment: .center)
.foregroundColor(self.isSelected ? Color.blue : Color.clear)
self.content()
}
.onTapGesture {
if(self.isSelectable) {
self.isSelected.toggle()
self.onSelectionChanged(self.isSelected)
}
}
}
func onSelectionChanged(callback: @escaping (_ isSelected: Bool) -> ()) -> some View {
CustomListRow(isSelectable: self.$isSelectable, onSelectionChanged: callback, content: self.content)
}
}
这是使用方法
struct ContentView: View {
var items = ["one", "two", "three", "four", "five", "six"]
var numberOfselectedItems = 3 // <- controlled by user input in real project
@State var selectedItems = Set<String>()
var body: some View {
List(items, id: \.self) { item in // <- id is \.id from datamodel in real project
CustomListRow(isSelectable: Binding(get: {
return (self.itemExist(item: item) || self.selectedItems.count < self.numberOfselectedItems)
}, set: { _ in})) {
Text("item: \(item) - Exist: \(self.itemExist(item: item) ? "true" : "false") - count: \(self.selectedItems.count)")
}
.onSelectionChanged { isSelected in
if(isSelected == true) {
self.selectedItems.insert(item)
} else {
self.selectedItems.remove(item)
}
}
}
}
func itemExist(item: String) -> Bool{
return self.selectedItems.contains(item)
}
}
您可以更进一步,创建一个自定义List
来使用此CustomListItemRow
,并在初始化器中传递几个额外的变量,例如Data
和{{1 }},并注意在自定义视图中控制选择,以使其在不同项目中可重用MaxSelectionSize
。但这超出了这个问题的范围。