swiftswiftuitabviewswiftui-tabview

How do I prevent the user from switching to certain tabs in a SwiftUI TabView


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.


Solution

  • 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])
        }
    }