I am creating sort of a game in swift that gives the user a new clue every time they guess incorrectly. I would like to have a TabView for the clues, but I don’t want the player to have access to every clue at the start. I was thinking either locking the tabs in the TabView until a function is called or making an array of different views in the TabView that can be edited.
CodePudding user response:
One note before starting my reply: in this community you need to be clear about the issue and show examples of your code, error messages, points where you get stuck. Your answer is quite generic, but I will give you some hints.
Each Tab is a view (almost) like any other one, it can be hidden conditionally.
You can just hide the tabs until the user reaches the point in the game where the clues must be shown. In addition, or in alternative, you can switch to different views to see each clue.
See an example below (there's room for improvement, this is the idea):
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")
}
}
}
}
CodePudding user response:
Unfortunately you cannot disable the standard TabBar selectors. But you can do your own custom ones, e.g. like this:
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])
}
}