SwiftUI 3 MacOs Таблица одиночного выбора и двойного щелчка по открытому листу
import SwiftUI
struct ContentView: View {
@State private var items: [ItemModel] = Array(0...100).map { ItemModel(id: $0, title: "item \($0)", age: $0) }
@State private var selection = Set<ItemModel.ID>()
@State private var sorting = [KeyPathComparator(\ItemModel.age)]
var body: some View {
Table(items, selection: $selection, sortOrder: $sorting) {
TableColumn("id", value: \.id) { Text("\($0.id)") }
TableColumn("title", value: \.title)
TableColumn("age", value: \.age) { Text("\($0.age)") }
}
.onChange(of: sorting) {
items.sort(using: $0)
}
.font(.caption)
.frame(width: 960, height: 540)
}
}
struct ItemModel: Identifiable {
var id: Int
var title: String
var age: Int
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
это рабочий пример таблицы, отсортированной по Model.age и поддерживающей множественный выбор, мне нужен одиночный выбор и открытый лист при двойном щелчке по строке, возможно ли это? также как мне получить выбранный объект элемента?
спасибо 🙏
3 ответа
Вы должны изменить
Set<Value.ID>
для
Value.ID
для выбора только одной строки и сделайте
TapGesture
в текст.
@State private var selection = Set<ItemModel.ID>() // <-- Use this for multiple rows selections
@State private var selection : ItemModel.ID? // <--- Use this for only one row selection
struct ContentView: View {
@State private var items: [ItemModel] = Array(0...100).map { ItemModel(id: $0, title: "item \($0)", age: $0) }
//@State private var selection = Set<ItemModel.ID>() <-- Use this for multiple rows selections
@State private var selection : ItemModel.ID? // <--- Use this for only one row selection
@State private var sorting = [KeyPathComparator(\ItemModel.age)]
@State private var showRow = false
var editRow: some View {
VStack {
Text(items[selection!].title)
.font(.title)
Text("Selected: \(selection.debugDescription)")
Button("Dismiss") {
showRow.toggle()
}.padding()
}
.frame(minWidth:400, minHeight: 400)
}
var body: some View {
VStack {
Table(items, selection: $selection, sortOrder: $sorting) {
TableColumn("id", value: \.id) {
Text("\($0.id)")
.onTapGesture(count: 2, perform: {
if selection != nil {
showRow.toggle()
}
})
}
TableColumn("title") { itemModel in
Text(itemModel.title)
.onTapGesture(count: 2, perform: {
if selection != nil {
showRow.toggle()
}
})
}
TableColumn("age", value: \.age) { Text("\($0.age)") }
}
.onChange(of: sorting) {
items.sort(using: $0)
}
.font(.caption)
.frame(width: 960, height: 540)
}
.sheet(isPresented: $showRow) {
editRow
}
}
}
Что касается двойного щелчка строки таблицы: Apple представила новый модификатор контекстного меню contextMenu(forSelectionType:menu:primaryAction:) в SwiftUI 4 на WWDC 2022. При этомprimaryAction
может быть предусмотрено, что выполняется, когда пользователь дважды щелкает наTable
ряд.
@State private var selection: ItemModel.ID?
var body: some View {
Table(items, selection: $selection, sortOrder: $sortOrder) {
TableColumn("id", value: \.id)
TableColumn("title", value: \.title)
TableColumn("age", value: \.age)
}
.contextMenu(forSelectionType: ItemModel.ID.self) { items in
// ...
} primaryAction: { items in
// This is executed when the row is double clicked
}
}
Как и Адам, в другом ответе есть ряд проблем с областью выбора и временем отклика.
Вы должны установить var selection как
ItemModel.ID?
но вы также должны обрабатывать действия щелчка по-разному.
Важно отметить, что это будет работать только с Big Sur.
То, как я обрабатываю различные действия для одиночных и двойных щелчков, таково:
.gesture(TapGesture(count: 2).onEnded {
print("double clicked")
})
.simultaneousGesture(TapGesture().onEnded {
print("single clicked")
})
Для вашего примера:
struct ContentView: View {
@State private var items: [ItemModel] = Array(0...100).map { ItemModel(id: $0, title: "item \($0)", age: $0) }
@State private var selection = ItemModel.ID?
@State private var sorting = [KeyPathComparator(\ItemModel.age)]
@State private var isShowingSheet: Bool = false
var body: some View {
Table(items, selection: $selection, sortOrder: $sorting) {
TableColumn("id", value: \.id) {
Text("\($0.id)").gesture(TapGesture(count: 2).onEnded {
self.
}).simultaneousGesture(TapGesture().onEnded {
self.selection = $0.id
})
}
TableColumn("title", value: \.title)
TableColumn("age", value: \.age) { Text("\($0.age)") }
}
.onChange(of: sorting) {
items.sort(using: $0)
}
.font(.caption)
.frame(width: 960, height: 540).sheet(isPresented: self.$isShowingSheet) {
Button("Close Sheet") { self.isShowingSheet = false } // <-- You may want to allow click to close sheet.
Text("Sheet Content Here")
}
}
}
Если вы хотите разрешить одиночный и двойной щелчок по всей строке, вам нужно, чтобы содержимое TableColumn заполнило всю ширину столбца и применило модификаторы к остальному содержимому TableColumn.