如何使用 SwiftUI 在 iPad 上运行拆分视图?

Dav*_*vid 4 ipad ios swiftui

似乎有一种简单的方法可以让漂亮的 iOS 应用程序在 iPad 空间上运行。一个不涉及重写 SwiftUI 应用程序的。

基本SplitView&SplitViewController问题似乎......就像一个深思熟虑的问题空间......我有一个基本的 - 带有 ContentView 的显示卡 - 我希望它在 iPad 上运行......只是一个更大的视口...... .

有什么简单的方法可以使用 SwiftUI 完成此操作吗?

Rol*_*tte 8

因此,这就是您按照Apple Fruta 应用程序示例使用 Xcode12,针对 iOS14 和 macOS11 作为最低目标设置 iPhone、iPad 和 mac 应用程序的方式。

使用这种实现 SwiftUI 的方式,您将拥有 iPad 和 Mac 使用的拆分视图。对于 iPhone,您将拥有经典的标签栏。

这是一个准备使用的代码,所以如果你不需要的Mac应用程序,只是删除的部分#else#end。我实施了它,以防其他人觉得它很方便。#if os(iOS)和之间的代码#else适用于 iPhone 和 iPad。

查找我在代码中添加的注释,这些注释解释了正在制作拆分视图的时间点。

根据设备保存导航类型的 ContentView:

struct ContentView: View {

  #if os(iOS)
  @Environment(\.horizontalSizeClass) private var horizontalSizeClass
  #endif

  @ViewBuilder
  var body: some View {
    #if os(iOS)
    if horizontalSizeClass == .compact {
      TabBarNavigationView()  // For iPhone
    }
    else {
      SidebarNavigationView()  // For iPad
    }
    #else
    SidebarNavigationView()  // For mac
      .frame(minWidth: 900, maxWidth: .infinity, minHeight: 500, maxHeight: .infinity)
    #endif
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,您使用您的选项卡枚举声明经典 iPhone 选项卡栏(HomeView 可以替换为您的任何 SwiftUI 视图):

enum TabItem {
  case home
}

struct TabBarNavigationView: View {

  @State private var selection: TabItem = .home

  var body: some View {
    TabView(selection: $selection) {

      NavigationView {
        HomeView()  // Create a SwiftUI HomeView or add your view
      }
      .tabItem {
        Image(systemName: "house")
          .font(.headline)
          .imageScale(.medium) }
      .tag(TabItem.home)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这是将容纳 iPad 和 mac 经典拆分视图的视图。当 iPad 处于纵向模式时,您的视图将作为导航,而将其添加到横向模式时,您的视图将被拆分。

struct SidebarNavigationView: View {

  @SceneStorage("selection")
  var selection: String?

  var content: some View {
    List(selection: $selection) {
      NavigationLink(destination: HomeView()) {
        Label(title: { Text("Home") },
              icon: { Image(systemName: "house")
                .font(.headline)
                .imageScale(.medium) })
      }
      .tag(NavigationItem.home)
    }
    .listStyle(SidebarListStyle())
  }

  var body: some View {
    NavigationView {
      #if os(iOS)
      content
      #else
      content
        .frame(minWidth: 200, idealWidth: 200, maxWidth: 200, maxHeight: .infinity)
        .toolbar {
          ToolbarItem(placement: .navigation) {
            Button(action: toggleSidebar ) {
              Image(systemName: "sidebar.left")
                .foregroundColor(.blue)
            }
          }
        }
      #endif

      // This is the part where the magic happens for the split view.
      // Instead of the Text, add any view you want in place.
      // Play here to see what fits best for you.
      Text("Content List")
        .frame(maxWidth: .infinity, maxHeight: .infinity)

      #if os(iOS)
      Text("Split view for iPad")
        .frame(maxWidth: .infinity, maxHeight: .infinity)
      #else
      Text("Split view for macOS")
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .toolbar { Spacer() }
      #endif
    }
  }
}

extension SidebarNavigationView {
  /// Show or hide the sidebar list in macOS.
  ///
  /// Needed for when the sidebar is hidden as there is a bug
  /// that unable the user to show the sidebar again if this
  /// hack is not enabled.
  func toggleSidebar() {
    #if os(macOS)
    NSApp
      .keyWindow?
      .firstResponder?
      .tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)),
                    with: nil)
    #endif
  }
}
Run Code Online (Sandbox Code Playgroud)