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

时间:2020-08-23 22:42:36

标签: ios ipad swiftui

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

基本的SplitViewSplitViewController问题似乎...好像是一个思想不周的问题空间...我有一个基本的问题-使用ContentView显示卡-我想要可以在iPad上运行...只是更大的视口...

有任何简单的方法可以使用SwiftUI吗?

1 个答案:

答案 0 :(得分:4)

因此,这是遵循Apple Fruta app示例(使用Xcode12来设置iOS,14和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
  }
}

然后,您将通过枚举标签来声明经典的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)
    }
  }
}

这是将保留iPad和Mac经典分割视图的视图。将iPad置于纵向模式时,视图将作为导航,而将其添加至横向时,视图将被拆分。

enum NavigationItem {
  case home
}

struct SidebarNavigationView: View {

  @State private var selection: Set<NavigationItem> = [.home]

  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
  }
}