SwiftUI:在 macOS 上获取侧边栏的折叠状态

4

我正在使用 NavigationView 在 macOS 上创建一个侧边栏。 我可以使用以下代码切换侧边栏:

Button {
    NSApp.keyWindow?.firstResponder?.tryToPerform(
    #selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
}

我现在正在尝试在侧边栏隐藏时显示标签。在按钮中触发这个操作不起作用,因为用户也可以通过调整大小来隐藏侧边栏。

NSSplitViewItem 上有一个 isCollapsed 属性,我想这可能是我需要检查的,但我不知道如何使用SwiftUI访问它。或者还有其他方法可以检查侧边栏的可见性吗?


如果您需要这样的功能,最好使用AppKit而不是那个hack,因为它可能会在下一个操作系统更新中停止工作。 - Asperi
这只是一个大型SwiftUI项目中非常微小的功能,我更愿意冒险它以后出现问题,也不想现在为了AppKit重写所有内容。因此,如果有一个hacky的解决方案,我很乐意采纳。 - viedev
2个回答

4

这个想法是找到仍然作为引擎内部使用的 NSSplitViewController 并订阅观察其第一个分割项(也就是我们的侧边栏)isCollapsed 状态。

在 Xcode 13.3 / macOS 12.2.1 上测试通过。

演示

以下是主要部分:

  // find split view through hierarchy
  while sview != nil, !sview!.isKind(of: NSSplitView.self) { 
    sview = sview?.superview
  }
  guard let sview = sview as? NSSplitView else { return }
  
  controller = sview.delegate as? NSSplitViewController   // delegate is our controller
  if let sideBar = controller?.splitViewItems.first {     // now observe for state
    observer = sideBar.observe(\.isCollapsed, options: [.new]) { [weak self] _, change in
      if let value = change.newValue {
        self?.sideCollapsed?.wrappedValue = value    // << here !!
      }
    }
  }

以及使用方式如下:

SideViewInsideNavigationView()
  .background(SplitViewAccessor(sideCollapsed: $collapsed))   // << inject finder !!

完整的研究结果和代码可在此处查看


4

使用 iOS 16+ 中的新NavigationSplitView,这变得更加容易。例如:

@State private var splitViewVisibility = NavigationSplitViewVisibility.all

var body: some View {
    NavigationSplitView(columnVisibility: $splitViewVisibility) {
        SidebarView()
    } detail: {
        DetailVew()
    }
    .onChange(of: splitViewVisibility) { newValue in
        print(newValue)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接