如何使用 SwiftUI 运行 iPad 上的拆分视图?
How to run the split view on iPad using SwiftUI?
似乎有一种简单的方法可以在 iPad space 上制作美观的 iOS 应用程序 运行。一个不涉及重写 SwiftUI 应用程序的方法。
基本的 SplitView
和 SplitViewController
问题似乎...很像一个考虑不周的问题 space...我有一个基本的 - 带有 ContentView 的显示卡- 我希望它在 iPad 上 运行...只是更大的视口...
有没有使用 SwiftUI 完成此操作的简单方法?
这就是您如何按照 Apple Fruta app 示例使用 Xcode12 设置 iPhone、iPad 和 mac 应用程序的方式,对于 [=32] =] 和 macOS11 作为最低目标。
使用这种实现 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 处于纵向模式时,您的视图将作为导航,而当将其添加到横向模式时,您的视图将被拆分。
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 from the user
/// action as there is a bug in this version of SwiftUI
/// that block the user to show the sidebar again without
/// this hack.
func toggleSidebar() {
#if os(macOS)
NSApp
.keyWindow?
.firstResponder?
.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)),
with: nil)
#endif
}
}
似乎有一种简单的方法可以在 iPad space 上制作美观的 iOS 应用程序 运行。一个不涉及重写 SwiftUI 应用程序的方法。
基本的 SplitView
和 SplitViewController
问题似乎...很像一个考虑不周的问题 space...我有一个基本的 - 带有 ContentView 的显示卡- 我希望它在 iPad 上 运行...只是更大的视口...
有没有使用 SwiftUI 完成此操作的简单方法?
这就是您如何按照 Apple Fruta app 示例使用 Xcode12 设置 iPhone、iPad 和 mac 应用程序的方式,对于 [=32] =] 和 macOS11 作为最低目标。
使用这种实现 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 处于纵向模式时,您的视图将作为导航,而当将其添加到横向模式时,您的视图将被拆分。
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 from the user
/// action as there is a bug in this version of SwiftUI
/// that block the user to show the sidebar again without
/// this hack.
func toggleSidebar() {
#if os(macOS)
NSApp
.keyWindow?
.firstResponder?
.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)),
with: nil)
#endif
}
}