如何在 SwiftUI 中使用 TabbedView?
How do I use TabbedView in SwiftUI?
struct ContentView : View {
var body: some View {
NavigationView {
TabbedView {
PasswordGenerator()
.tabItemLabel {
Image("KeyGlyph")
Text("Generator")
}
PasswordGeneratorSettings()
.tabItemLabel {
Image("SettingsGlyph")
Text("Settings")
}
}
}
}
}
这不会编译,但在 WWDC 的 Swift Essentials 视频中使用了它(请参阅分钟 54:30)并且我已经看到了一些解决方法,例如 VStack 解决方法(但即便如此许多缺陷,左侧选项卡向左太远,右侧选项卡向右太远,切换选项卡时,只有第一个最初加载的选项卡加载,另一个选项卡保持空白,使用标签无济于事)。那么我如何拥有两个加载视图并具有图像和文本的选项卡?
'TabbedView'的使用方法类似如下:
struct TabView : View {
@State private var selection = 1
var body: some View {
TabbedView (selection: $selection) {
InboxList()
.tabItemLabel(selection == 1 ? Image("second") : Image("first"))
.tag(1)
PostsList()
.tabItemLabel(Image("first"))
.tag(2)
Something()
.tabItemLabel(Image("first"))
.tag(3)
}
}
}
我不确定为什么您的示例无法编译,但您错过了每个 "tab" 上的 selection
参数和 .tag
属性。
顺便说一句,在当前 XCode 版本(测试版 2)中,您不能同时显示文本和图像作为标签。
您的代码 应该 有效,但这是一个已知问题,来自 iOS & iPadOS 13 Beta 2 Release Notes:
The tabItemLabel(_:) modifier doesn’t accept @ViewBuilder closures.
在解决此问题之前,唯一的解决方法是使用您提到的 VStack。
MyView()
.tabItemLabel(VStack {
Image("resourceName")
Text("Item")
})
更新:
此问题已通过 Xcode 11 beta 3 修复:
The tabItemLabel(:) modifier — now named tabItem(:) — now accepts
@ViewBuilder closures.
示例:
.tabItem {
Image(systemName: "circle")
Text("Tab1")
}
对于 XCode beta 3,以下应该有效:
import SwiftUI
struct Home : View {
@State private var currentTab = 1
var body: some View {
TabbedView(selection: $currentTab) {
FirstView()
.tabItem {
VStack {
Image(systemName: "1.circle")
Text("First Tab")
}
}.tag(1)
SecondView()
.tabItem {
VStack {
Image(systemName: "2.circle")
Text("Second Tab")
}
}.tag(2)
}
}
}
不过,将选项卡标签包含在 VStack
中似乎是可选的。因此,您可能决定放弃它,例如:
import SwiftUI
struct Home : View {
@State private var currentTab = 1
var body: some View {
TabbedView(selection: $currentTab) {
FirstView()
.tabItem {
Image(systemName: "1.circle")
Text("First Tab")
}.tag(1)
SecondView()
.tabItem {
Image(systemName: "2.circle")
Text("Second Tab")
}.tag(2)
}
}
}
TabbedView 已弃用。
您现在可以使用 TabView
struct AppTabbedView: View {
@State private var selection = 3
var body: some View {
TabView (selection:$selection){
Text("The First Tab")
.tabItem {
Image(systemName: "1.square.fill")
Text("First")
}
.tag(1)
Text("Another Tab")
.tabItem {
Image(systemName: "2.square.fill")
Text("Second")
}.tag(2)
Text("The Last Tab")
.tabItem {
Image(systemName: "3.square.fill")
Text("Third")
}.tag(3)
}
.font(.headline)
}
}
从 Xcode 11 GM 开始,此代码有效:(来自 https://developer.apple.com/documentation/swiftui/tabview)
TabView {
Text("The First Tab")
.tabItem {
Image(systemName: "1.square.fill")
Text("First")
}
Text("Another Tab")
.tabItem {
Image(systemName: "2.square.fill")
Text("Second")
}
Text("The Last Tab")
.tabItem {
Image(systemName: "3.square.fill")
Text("Third")
}
}
.font(.headline)
对于那些仍在寻找如何做到这一点的人,这里有 Xcode 11 GM 的更新。
struct Tabs: View {
@State private var selected = 0
var body: some View {
TabView(selection: $selected) {
MyFirstView()
.tabItem {
Image(systemName: (selected == 0 ? "star.fill" : "star"))
Text("One")
}.tag(0)
MySecondView()
.tabItem {
Image(systemName: (selected == 1 ? "star.fill" : "star"))
Text("Two")
}.tag(1)
MyThirdView()
.tabItem {
Image(systemName: (selected == 2 ? "star.fill" : "star"))
Text("Three")
}.tag(2)
}
.edgesIgnoringSafeArea(.all) // Important if you want NavigationViews to go under the status bar...
}
}
TabbedView 已弃用并已重命名为 TabView
你可以像这样使用 TabView
TabView {
(Text("Tab 1!").tabItem {
Text("First")
})
(Text("Tab 2!").tabItem {
Text("Second")
})
}
TabbedView()
已弃用,请改用 TabView()
。
对 select 视图使用整数对我来说很难闻,从我使用 UIButton 和 UIView 的 tag()
开始,最好枚举你正在做的事情而不是分配硬编码值范围非常大。即 Int.min()
到 Int.max()
。这也使得代码在未来更容易阅读和维护。
TabView(selection: )
可用于select索引,声明为:
public struct TabView<SelectionValue, Content> : View where SelectionValue : Hashable, Content : View {
public init(selection: Binding<SelectionValue>?, @ViewBuilder content: () -> Content)
…
这意味着您可以 select 具有任何可散列内容的索引。
我们可以使用符合 Hashable
的 enum
来包含选项卡列表,
这样以后可以使用一个 Observable 来帮助控制和加载视图的状态。或者将枚举作为应用程序状态的一部分。我相信您可以使用大量资源来找到满足您需求的合适解决方案。
struct MainTabView: View {
@State private var selection: Tabs = .profile
private enum Tabs: Hashable {
case content
case profile
}
var body: some View {
TabView(selection: $selection) {
// Learn Content
Text("The First Tab")
.tabItem {
Image(systemName: "book")
Text("Learn")
}.tag(Tabs.content)
// The Users Profile View.
ProfileView()
.tabItem {
Image(systemName: "person.circle")
Text("Profile")
}.tag(Tabs.profile)
}
}
}
struct ContentView : View {
var body: some View {
NavigationView {
TabbedView {
PasswordGenerator()
.tabItemLabel {
Image("KeyGlyph")
Text("Generator")
}
PasswordGeneratorSettings()
.tabItemLabel {
Image("SettingsGlyph")
Text("Settings")
}
}
}
}
}
这不会编译,但在 WWDC 的 Swift Essentials 视频中使用了它(请参阅分钟 54:30)并且我已经看到了一些解决方法,例如 VStack 解决方法(但即便如此许多缺陷,左侧选项卡向左太远,右侧选项卡向右太远,切换选项卡时,只有第一个最初加载的选项卡加载,另一个选项卡保持空白,使用标签无济于事)。那么我如何拥有两个加载视图并具有图像和文本的选项卡?
'TabbedView'的使用方法类似如下:
struct TabView : View {
@State private var selection = 1
var body: some View {
TabbedView (selection: $selection) {
InboxList()
.tabItemLabel(selection == 1 ? Image("second") : Image("first"))
.tag(1)
PostsList()
.tabItemLabel(Image("first"))
.tag(2)
Something()
.tabItemLabel(Image("first"))
.tag(3)
}
}
}
我不确定为什么您的示例无法编译,但您错过了每个 "tab" 上的 selection
参数和 .tag
属性。
顺便说一句,在当前 XCode 版本(测试版 2)中,您不能同时显示文本和图像作为标签。
您的代码 应该 有效,但这是一个已知问题,来自 iOS & iPadOS 13 Beta 2 Release Notes:
The tabItemLabel(_:) modifier doesn’t accept @ViewBuilder closures.
在解决此问题之前,唯一的解决方法是使用您提到的 VStack。
MyView()
.tabItemLabel(VStack {
Image("resourceName")
Text("Item")
})
更新:
此问题已通过 Xcode 11 beta 3 修复:
The tabItemLabel(:) modifier — now named tabItem(:) — now accepts @ViewBuilder closures.
示例:
.tabItem {
Image(systemName: "circle")
Text("Tab1")
}
对于 XCode beta 3,以下应该有效:
import SwiftUI
struct Home : View {
@State private var currentTab = 1
var body: some View {
TabbedView(selection: $currentTab) {
FirstView()
.tabItem {
VStack {
Image(systemName: "1.circle")
Text("First Tab")
}
}.tag(1)
SecondView()
.tabItem {
VStack {
Image(systemName: "2.circle")
Text("Second Tab")
}
}.tag(2)
}
}
}
不过,将选项卡标签包含在 VStack
中似乎是可选的。因此,您可能决定放弃它,例如:
import SwiftUI
struct Home : View {
@State private var currentTab = 1
var body: some View {
TabbedView(selection: $currentTab) {
FirstView()
.tabItem {
Image(systemName: "1.circle")
Text("First Tab")
}.tag(1)
SecondView()
.tabItem {
Image(systemName: "2.circle")
Text("Second Tab")
}.tag(2)
}
}
}
TabbedView 已弃用。
您现在可以使用 TabView
struct AppTabbedView: View {
@State private var selection = 3
var body: some View {
TabView (selection:$selection){
Text("The First Tab")
.tabItem {
Image(systemName: "1.square.fill")
Text("First")
}
.tag(1)
Text("Another Tab")
.tabItem {
Image(systemName: "2.square.fill")
Text("Second")
}.tag(2)
Text("The Last Tab")
.tabItem {
Image(systemName: "3.square.fill")
Text("Third")
}.tag(3)
}
.font(.headline)
}
}
从 Xcode 11 GM 开始,此代码有效:(来自 https://developer.apple.com/documentation/swiftui/tabview)
TabView {
Text("The First Tab")
.tabItem {
Image(systemName: "1.square.fill")
Text("First")
}
Text("Another Tab")
.tabItem {
Image(systemName: "2.square.fill")
Text("Second")
}
Text("The Last Tab")
.tabItem {
Image(systemName: "3.square.fill")
Text("Third")
}
}
.font(.headline)
对于那些仍在寻找如何做到这一点的人,这里有 Xcode 11 GM 的更新。
struct Tabs: View {
@State private var selected = 0
var body: some View {
TabView(selection: $selected) {
MyFirstView()
.tabItem {
Image(systemName: (selected == 0 ? "star.fill" : "star"))
Text("One")
}.tag(0)
MySecondView()
.tabItem {
Image(systemName: (selected == 1 ? "star.fill" : "star"))
Text("Two")
}.tag(1)
MyThirdView()
.tabItem {
Image(systemName: (selected == 2 ? "star.fill" : "star"))
Text("Three")
}.tag(2)
}
.edgesIgnoringSafeArea(.all) // Important if you want NavigationViews to go under the status bar...
}
}
TabbedView 已弃用并已重命名为 TabView 你可以像这样使用 TabView
TabView {
(Text("Tab 1!").tabItem {
Text("First")
})
(Text("Tab 2!").tabItem {
Text("Second")
})
}
TabbedView()
已弃用,请改用 TabView()
。
对 select 视图使用整数对我来说很难闻,从我使用 UIButton 和 UIView 的 tag()
开始,最好枚举你正在做的事情而不是分配硬编码值范围非常大。即 Int.min()
到 Int.max()
。这也使得代码在未来更容易阅读和维护。
TabView(selection: )
可用于select索引,声明为:
public struct TabView<SelectionValue, Content> : View where SelectionValue : Hashable, Content : View {
public init(selection: Binding<SelectionValue>?, @ViewBuilder content: () -> Content)
…
这意味着您可以 select 具有任何可散列内容的索引。
我们可以使用符合 Hashable
的 enum
来包含选项卡列表,
这样以后可以使用一个 Observable 来帮助控制和加载视图的状态。或者将枚举作为应用程序状态的一部分。我相信您可以使用大量资源来找到满足您需求的合适解决方案。
struct MainTabView: View {
@State private var selection: Tabs = .profile
private enum Tabs: Hashable {
case content
case profile
}
var body: some View {
TabView(selection: $selection) {
// Learn Content
Text("The First Tab")
.tabItem {
Image(systemName: "book")
Text("Learn")
}.tag(Tabs.content)
// The Users Profile View.
ProfileView()
.tabItem {
Image(systemName: "person.circle")
Text("Profile")
}.tag(Tabs.profile)
}
}
}