我想使用SwiftUI构建一个非常简单的iOS 14侧边栏。
设置非常简单,我有三个视图HomeView
,LibraryView
和SettingsView
,还有一个代表每个屏幕的枚举。
enum Screen: Hashable {
case home, library, settings
}
我的最终目标是根据大小级别自动在选项卡视图和侧边栏之间切换,但是某些功能并不能按预期工作。
全局状态由MainNavigationView
拥有,这也是我的WindowGroup
的根视图。
struct MainNavigationView: View {
@State var screen: Screen? = .home
var body: some View {
NavigationView {
SidebarView(state: $screen)
}
.navigationViewStyle(DoubleColumnNavigationViewStyle())
}
}
SidebarView
是一个简单的List
,包含三个NavigationLink
,每个Screen
一个。
struct SidebarView: View {
@Binding var state: Screen?
var body: some View {
List {
NavigationLink(
destination: HomeView(),
tag: Screen.home,
selection: $state,
label: {
Label("Home", systemImage: "house" )
})
NavigationLink(
destination: LibraryView(),
tag: Screen.library,
selection: $state,
label: {
Label("Library", systemImage: "book")
})
NavigationLink(
destination: SettingsView(),
tag: Screen.settings,
selection: $state,
label: {
Label("Settings", systemImage: "gearshape")
})
}
.listStyle(SidebarListStyle())
.navigationTitle("Sidebar")
}
}
我使用NavigationLink(destination:tag:selection:label)
初始化程序,以便在我的MainNavigationView
中设置选定的屏幕,以便以后可以将其重新用于TabView
。
但是,很多事情并没有达到预期效果。
首先,在人像模式iPad(我使用11英寸iPad Pro仿真器)中启动应用程序时,在启动应用程序时未选择任何屏幕。只有在导航栏中单击 Back 后,才会显示初始屏幕,并显示我的主视图。
第二个奇怪的事情是,每当隐藏侧边栏时,绑定似乎都设置为nil
。在横向模式下,视图按预期方式工作,但是在切换侧栏以隐藏然后再次显示时,选择会丢失。
内容视图保持正确,但是侧边栏选择丢失。
这些仅仅是SwiftUI
的错误还是使用Binding
创建侧边栏的另一种方式?
答案 0 :(得分:4)
您需要在NavigationView { }
中包括一个默认的辅助视图,通常它是一个占位符,但是您可以使用HomeScreen
,例如
struct MainNavigationView: View {
@State var screen: Screen? = .home
var body: some View {
NavigationView {
SidebarView(state: $screen)
HomeScreen()
}
.navigationViewStyle(DoubleColumnNavigationViewStyle())
}
}
关于未重新选择单元格的问题-从iOS 14.2开始,没有列表选择绑定(处于非编辑模式时),因此选择丢失。尽管List API具有一个$selection
参数,但目前仅在macOS上受支持。您可以看到该信息的标题:
/// On iOS and tvOS, you must explicitly put the list into edit mode for
/// the selection to apply.
这有点令人费解,但这意味着我们需要侧边栏的选择绑定仅适用于macOS,在iOS上仅适用于编辑模式下的多选(即复选标记)。原因可能是因为UITableView
的选择是事件驱动的,也许不可能转化为SwiftUI的状态驱动性质。如果您曾经尝试过将状态推到导航控制器上来进行状态还原,并尝试在弹出时显示单元格非突出显示的动画,并且该表视图未加载并且单元格从未被突出显示,那么您将明白我的意思了吗。同步加载表,绘制选定的单元格然后开始超高显示动画是一场噩梦。我希望苹果公司将在纯SwiftUI中重新实现List,Sidebar和NavigationView来克服这些问题,所以现在我们只需要忍受它即可。
此问题一旦解决,将像在MacOS上工作一样简单List(selection:$screen) { }
。作为iOS上的一种解决方法,您可以以自己的方式突出显示图标或文字,例如尝试使用粗体文本:
NavigationLink(
destination: HomeView(),
tag: Screen.home,
selection: $state,
label: {
Label("Home", systemImage: "house" )
})
.font(Font.headline.weight(state == Screen.home ? .bold : .regular))
紧凑时看起来不太好,因为在弹出主视图后,当未突出显示行时,将删除粗体。在这种情况下,可能有一种禁用粗体的方法。
还有两个您应该注意的错误: