如何防止用户切换到 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])
    }
}