macOS 上的 SwiftUI:具有详细视图和多项选择的列表 [英] SwiftUI on macOS: list with detail view and multiple selection
问题描述
TL;DR:
我无法在 macOS 上创建包含详细信息视图和多项选择的列表.
I cannot have a list with a detail view and multiple selections on macOS.
更详细:
为了演示我的问题,我做了一个小示例项目.用户界面如下所示:
For demonstration purposes of my issue, I made a small example project. The UI looks as follows:
这是应用程序"启动时,顶部有一个列表,下面有一个详细的表示.因为我使用的是列表的初始化程序 init(_:selection:rowContent:)
,其中 selection
的类型是 Binding
根据Apple的文档,我可以免费使用键盘箭头键选择项目.
This is the "app" when launched, with a list on top and a detail representation below. Because I am using the List's initialiser init(_:selection:rowContent:)
, where selection
is of type Binding<SelectionValue?>?
according to Apple's documentation, I get selecting items with the keyboard arrow keys for free.
完整代码如下:
import SwiftUI
@main
struct UseCurorsInLisstApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(ViewModel())
}
}
}
class ViewModel: ObservableObject {
@Published var items = [Item(), Item(), Item(), Item(), Item()]
@Published var selectedItem: Item? = nil
}
struct Item: Identifiable, Hashable {
let id = UUID()
}
struct ContentView: View {
@EnvironmentObject var vm: ViewModel
var body: some View {
VStack {
List(vm.items, id: \.self, selection: $vm.selectedItem) { item in
VStack {
Text("Item \(item.id.uuidString)")
Divider()
}
}
Divider()
Group {
if let item = vm.selectedItem {
Text("Detail item \(item.id.uuidString)")
} else {
Text("No selection…")
}
}
.frame(minHeight: 200.0, maxHeight: .infinity)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
现在,到目前为止已经取得了成功,我认为能够选择多于一行会很有用,所以我仔细研究了 List(_:selection:rowContent:)
,其中 selection
的类型为 Binding
.为了能够有详细的视图,我只是对
Now, having had success with this so far, I figured being able to select more than one row would be useful, so I took a closer look into List(_:selection:rowContent:)
, where selection
is of type Binding<Set<SelectionValue>>?
. To be able to have a detail view, I just made a few minor changes to
ViewModel
:
class ViewModel: ObservableObject {
@Published var items = [Item(), Item(), Item(), Item(), Item()]
@Published var selectedItem: Item? = nil
@Published var selectedItems: Set<Item>? = nil {
didSet {
if selectedItems?.count == 1, let item = selectedItems?.first {
selectedItem = item
}
}
}
}
和 ContentView
:
struct ContentView: View {
@EnvironmentObject var vm: ViewModel
var body: some View {
VStack {
List(vm.items, id: \.self, selection: $vm.selectedItems) { item in
VStack {
Text("Item \(item.id.uuidString)")
Divider()
}
}
Divider()
Group {
if vm.selectedItems?.count == 1, let item = vm.selectedItems?.first {
Text("Detail item \(item.id.uuidString)")
} else {
Text("No or multiple selection…")
}
}
.frame(minHeight: 200.0, maxHeight: .infinity)
}
}
}
现在的问题是我无法再选择行中的项目,无论是通过单击还是通过箭头键.这是我遇到的限制还是我认为它错了"?
The problem now is that I cannot select an item of the row any more, neither by clicking, nor by arrow keys. Is this a limitation I am running into or am I "holding it wrong"?
推荐答案
使用按钮并将其插入到集合中.键盘选择也适用于 shift +(向上/向下箭头)
Use the button and insert it into the set. Keyboard selection also works with shift + (up/down arrow)
class ViewModel: ObservableObject {
@Published var items = [Item(), Item(), Item(), Item(), Item()]
@Published var selectedItem: Item? = nil
@Published var selectedItems: Set<Item> = []
}
struct ContentView: View {
@EnvironmentObject var vm: ViewModel
var body: some View {
VStack {
List(vm.items, id: \.self, selection: $vm.selectedItems) { item in
Button {
vm.selectedItem = item
vm.selectedItems.insert(item)
} label: {
VStack {
Text("Item \(item.id.uuidString)")
Divider()
}
}
.buttonStyle(PlainButtonStyle())
}
Divider()
Group {
if let item = vm.selectedItem {
Text("Detail item \(item.id.uuidString)")
} else {
Text("No or multiple selection…")
}
}
.frame(minHeight: 200.0, maxHeight: .infinity)
}
}
}
添加删除:
Button {
vm.selectedItem = item
if vm.selectedItems.contains(item) {
vm.selectedItems.remove(item)
} else {
vm.selectedItems.insert(item)
}
}
编辑简单的需要给一个空白的默认值来设置.因为在 nil 中它永远不会追加到 set 需要初始化.
Edit In simple need to give a blank default value to set. because in nil it will never append to set need initialization.
@Published var selectedItems: Set<Item> = [] {
这篇关于macOS 上的 SwiftUI:具有详细视图和多项选择的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!