使用 SwiftUI 时调整 NSSplitViewController 的大小
Resizing NSSplitViewController when using SwiftUI
我正在尝试在 SwiftUI 中使用 NSSplitViewController 并有一个简单的主视图和详细视图,如下面的代码片段所示。这工作正常,但是在 window 调整大小时 SplitView 无法扩展,而在视图调试器中我看到几何具有调整大小的尺寸 window.
如何根据 window 尺寸(或 GeometryReader)调整 SplitView 的大小。
struct SampleView: View {
@EnvironmentObject var env : AppEnvironment
var body: some View {
Group {
if (self.env.files.isEmpty) {
Text("loading")
} else {
GeometryReader { geometry in
SplitView(master: {
Text("master")
.background(Color.yellow)
}, detail: {
Text("Detail")
.background(Color.orange)
}).frame(width: geometry.size.height, height: geometry.size.height)
}
}
}
}
}
下面是 SplitView 的实现
//
// Source: https://gist.github.com/HashNuke/f8895192fff1f275e66c30340f304d80
//
struct SplitView<Master: View, Detail: View>: View {
var master: Master
var detail: Detail
init(@ViewBuilder master: () -> Master, @ViewBuilder detail: () -> Detail) {
self.master = master()
self.detail = detail()
}
var body: some View {
let viewControllers = [NSHostingController(rootView: master), NSHostingController(rootView: detail)]
return SplitViewController(viewControllers: viewControllers)
}
}
struct SplitViewController: NSViewControllerRepresentable {
var viewControllers: [NSViewController]
private let splitViewResorationIdentifier = "com.company.restorationId:mainSplitViewController"
func makeNSViewController(context: Context) -> NSViewController {
let controller = NSSplitViewController()
controller.splitView.dividerStyle = .thin
controller.splitView.autosaveName = NSSplitView.AutosaveName(splitViewResorationIdentifier)
controller.splitView.identifier = NSUserInterfaceItemIdentifier(rawValue: splitViewResorationIdentifier)
let vcLeft = viewControllers[0]
let vcRight = viewControllers[1]
vcLeft.view.widthAnchor.constraint(greaterThanOrEqualToConstant: 30).isActive = true
vcRight.view.widthAnchor.constraint(greaterThanOrEqualToConstant: 70).isActive = true
let sidebarItem = NSSplitViewItem(contentListWithViewController: vcLeft)
sidebarItem.canCollapse = false
// I'm not sure if this has any impact
// controller.view.frame = CGRect(origin: .zero, size: CGSize(width: 800, height: 800))
controller.addSplitViewItem(sidebarItem)
let mainItem = NSSplitViewItem(viewController: vcRight)
controller.addSplitViewItem(mainItem)
return controller
}
func updateNSViewController(_ nsViewController: NSViewController, context: Context) {
print("should update splitView", nsViewController.view.superview?.frame, nsViewController.view.frame)
}
}
问题不在拆分视图中,而是在内容子视图中,因为默认情况下 SwiftUI 视图被收紧到内容,所以下面
SplitView(master: {
Text("master") // Master content view
.frame(maxWidth: .infinity, maxHeight: .infinity) // << here !!
.background(Color.yellow)
}, detail: {
Text("Detail") // Details content view
.frame(maxWidth: .infinity, maxHeight: .infinity) // << here !!
.background(Color.orange)
})
给出了预期的结果
注意:我用了.frame(width: geometry.size.width, height: geometry.size.height)
,`因为我认为这是一个错字。
我正在尝试在 SwiftUI 中使用 NSSplitViewController 并有一个简单的主视图和详细视图,如下面的代码片段所示。这工作正常,但是在 window 调整大小时 SplitView 无法扩展,而在视图调试器中我看到几何具有调整大小的尺寸 window.
如何根据 window 尺寸(或 GeometryReader)调整 SplitView 的大小。
struct SampleView: View {
@EnvironmentObject var env : AppEnvironment
var body: some View {
Group {
if (self.env.files.isEmpty) {
Text("loading")
} else {
GeometryReader { geometry in
SplitView(master: {
Text("master")
.background(Color.yellow)
}, detail: {
Text("Detail")
.background(Color.orange)
}).frame(width: geometry.size.height, height: geometry.size.height)
}
}
}
}
}
下面是 SplitView 的实现
//
// Source: https://gist.github.com/HashNuke/f8895192fff1f275e66c30340f304d80
//
struct SplitView<Master: View, Detail: View>: View {
var master: Master
var detail: Detail
init(@ViewBuilder master: () -> Master, @ViewBuilder detail: () -> Detail) {
self.master = master()
self.detail = detail()
}
var body: some View {
let viewControllers = [NSHostingController(rootView: master), NSHostingController(rootView: detail)]
return SplitViewController(viewControllers: viewControllers)
}
}
struct SplitViewController: NSViewControllerRepresentable {
var viewControllers: [NSViewController]
private let splitViewResorationIdentifier = "com.company.restorationId:mainSplitViewController"
func makeNSViewController(context: Context) -> NSViewController {
let controller = NSSplitViewController()
controller.splitView.dividerStyle = .thin
controller.splitView.autosaveName = NSSplitView.AutosaveName(splitViewResorationIdentifier)
controller.splitView.identifier = NSUserInterfaceItemIdentifier(rawValue: splitViewResorationIdentifier)
let vcLeft = viewControllers[0]
let vcRight = viewControllers[1]
vcLeft.view.widthAnchor.constraint(greaterThanOrEqualToConstant: 30).isActive = true
vcRight.view.widthAnchor.constraint(greaterThanOrEqualToConstant: 70).isActive = true
let sidebarItem = NSSplitViewItem(contentListWithViewController: vcLeft)
sidebarItem.canCollapse = false
// I'm not sure if this has any impact
// controller.view.frame = CGRect(origin: .zero, size: CGSize(width: 800, height: 800))
controller.addSplitViewItem(sidebarItem)
let mainItem = NSSplitViewItem(viewController: vcRight)
controller.addSplitViewItem(mainItem)
return controller
}
func updateNSViewController(_ nsViewController: NSViewController, context: Context) {
print("should update splitView", nsViewController.view.superview?.frame, nsViewController.view.frame)
}
}
问题不在拆分视图中,而是在内容子视图中,因为默认情况下 SwiftUI 视图被收紧到内容,所以下面
SplitView(master: {
Text("master") // Master content view
.frame(maxWidth: .infinity, maxHeight: .infinity) // << here !!
.background(Color.yellow)
}, detail: {
Text("Detail") // Details content view
.frame(maxWidth: .infinity, maxHeight: .infinity) // << here !!
.background(Color.orange)
})
给出了预期的结果
注意:我用了.frame(width: geometry.size.width, height: geometry.size.height)
,`因为我认为这是一个错字。