如何防止用户切换到 SwiftUI TabView 中的某些选项卡
How do I prevent the user from switching to certain tabs in a SwiftUI TabView
我正在 swift 中创建一种游戏,在用户每次猜错时为他们提供新线索。我想为线索提供一个 TabView,但我不希望玩家在一开始就可以访问每条线索。我在考虑要么锁定 TabView 中的选项卡直到调用函数,要么在 TabView 中创建一个可以编辑的不同视图数组。
开始我的回复之前的一个注意事项:在这个社区中,您需要清楚地了解问题并展示您的代码示例、错误消息、卡住的地方。你的回答很笼统,但我会给你一些提示。
每个选项卡(几乎)都是一个视图,可以有条件地隐藏。
您可以只隐藏选项卡,直到用户到达游戏中必须显示线索的位置。此外,或者替代地,您可以切换到不同的视图来查看每条线索。
看下面的例子(还有改进的余地,就是这个思路):
struct Tabs: View {
@State private var showTab2 = false // This will trigger the tab to be shown
// It can be stored in your view model
var body: some View {
TabView {
Example(showNextClue: $showTab2)
.tabItem {Label("Tab 1", systemImage: "checkmark")}
if showTab2 { // Tab 2 is hidden until you change the state variable
Tab2()
.tabItem {Label("Tab 2", systemImage: "flag")}
}
Example(showNextClue: $showTab2)
.tabItem {Label("Tab 3", systemImage: "trash")}
}
}
}
struct Tab2: View {
@State private var clueIndex = 0 // What clue will you show now?
var body: some View {
VStack {
switch clueIndex { // Show the applicable clue
// You can iterate through an array of views as you proposed, chose the best method
case 0:
Text("Now you can see this clue number 1")
case 1:
Text("Clue number 2")
default:
Text("Clue \(String(clueIndex))")
}
Button {
clueIndex += 1
} label: {
Text("Show next clue")
}
.padding()
}
}
}
struct Example: View {
@Binding var showNextClue: Bool
var body: some View {
VStack {
Text("This is open")
.padding()
Button {
showNextClue.toggle()
} label: {
Text(showNextClue ? "Now you can see the next clue" : "Click here to see your next clue")
}
}
}
}
很遗憾,您无法禁用标准的 TabBar 选择器。但是你可以做你自己的定制,例如像这样:
struct ContentView: View {
@State private var currentTab = "Home"
@State private var activeTabs: Set<String> = ["Home"] // saves the activated tabs
var body: some View {
VStack {
TabView(selection: $currentTab) {
// Tab Home
VStack(spacing: 20) {
Text("Home Tab")
Button("Unlock Hint 1") { activeTabs.insert("Hint 1")}
Button("Unlock Hint 2") { activeTabs.insert("Hint 2")}
}
.tag("Home")
// Tab 1. Hint
VStack {
Text("Your first Hint")
}
.tag("Hint 1")
// Tab 2. Hint
VStack {
Text("Your Second Hint")
}
.tag("Hint 2")
}
// custom Tabbar buttons
Divider()
HStack {
OwnTabBarButton("Home", imageName: "house.fill")
OwnTabBarButton("Hint 1", imageName: "1.circle")
OwnTabBarButton("Hint 2", imageName: "2.circle")
}
}
}
func OwnTabBarButton(_ label: String, imageName: String) -> some View {
Button {
currentTab = label
} label: {
VStack {
Image(systemName: imageName)
Text(label)
}
}
.disabled(!activeTabs.contains(label))
.padding([.horizontal,.top])
}
}
我正在 swift 中创建一种游戏,在用户每次猜错时为他们提供新线索。我想为线索提供一个 TabView,但我不希望玩家在一开始就可以访问每条线索。我在考虑要么锁定 TabView 中的选项卡直到调用函数,要么在 TabView 中创建一个可以编辑的不同视图数组。
开始我的回复之前的一个注意事项:在这个社区中,您需要清楚地了解问题并展示您的代码示例、错误消息、卡住的地方。你的回答很笼统,但我会给你一些提示。
每个选项卡(几乎)都是一个视图,可以有条件地隐藏。
您可以只隐藏选项卡,直到用户到达游戏中必须显示线索的位置。此外,或者替代地,您可以切换到不同的视图来查看每条线索。
看下面的例子(还有改进的余地,就是这个思路):
struct Tabs: View {
@State private var showTab2 = false // This will trigger the tab to be shown
// It can be stored in your view model
var body: some View {
TabView {
Example(showNextClue: $showTab2)
.tabItem {Label("Tab 1", systemImage: "checkmark")}
if showTab2 { // Tab 2 is hidden until you change the state variable
Tab2()
.tabItem {Label("Tab 2", systemImage: "flag")}
}
Example(showNextClue: $showTab2)
.tabItem {Label("Tab 3", systemImage: "trash")}
}
}
}
struct Tab2: View {
@State private var clueIndex = 0 // What clue will you show now?
var body: some View {
VStack {
switch clueIndex { // Show the applicable clue
// You can iterate through an array of views as you proposed, chose the best method
case 0:
Text("Now you can see this clue number 1")
case 1:
Text("Clue number 2")
default:
Text("Clue \(String(clueIndex))")
}
Button {
clueIndex += 1
} label: {
Text("Show next clue")
}
.padding()
}
}
}
struct Example: View {
@Binding var showNextClue: Bool
var body: some View {
VStack {
Text("This is open")
.padding()
Button {
showNextClue.toggle()
} label: {
Text(showNextClue ? "Now you can see the next clue" : "Click here to see your next clue")
}
}
}
}
很遗憾,您无法禁用标准的 TabBar 选择器。但是你可以做你自己的定制,例如像这样:
struct ContentView: View {
@State private var currentTab = "Home"
@State private var activeTabs: Set<String> = ["Home"] // saves the activated tabs
var body: some View {
VStack {
TabView(selection: $currentTab) {
// Tab Home
VStack(spacing: 20) {
Text("Home Tab")
Button("Unlock Hint 1") { activeTabs.insert("Hint 1")}
Button("Unlock Hint 2") { activeTabs.insert("Hint 2")}
}
.tag("Home")
// Tab 1. Hint
VStack {
Text("Your first Hint")
}
.tag("Hint 1")
// Tab 2. Hint
VStack {
Text("Your Second Hint")
}
.tag("Hint 2")
}
// custom Tabbar buttons
Divider()
HStack {
OwnTabBarButton("Home", imageName: "house.fill")
OwnTabBarButton("Hint 1", imageName: "1.circle")
OwnTabBarButton("Hint 2", imageName: "2.circle")
}
}
}
func OwnTabBarButton(_ label: String, imageName: String) -> some View {
Button {
currentTab = label
} label: {
VStack {
Image(systemName: imageName)
Text(label)
}
}
.disabled(!activeTabs.contains(label))
.padding([.horizontal,.top])
}
}