2

I have a TabView with three TabItems. When I press a Button on the first TabItem, I then want to disable the user's ability to tap and go to TabItem two and three.

I've used disabled(), but I can still tap and go to them.

TabView(selection: $tabSelected) {
    MeditationTimer(vm: vm)
        .tabItem({
            Label("Meditate", systemImage: "timer")
        })
        .tag(0)
    
    History(vm: vm)
        .tabItem {
            Label("Sessions", systemImage: "list.bullet")
        }
        .tag(1)
        .disabled(vm.isActive)

    Settings(vm: vm)
        .tabItem {
            Label("Settings", systemImage: "gearshape")
        }
        .tag(2)
        .disabled(vm.isActive)
}

Putting .disabled() on TabView itself actually works, but yeah, then nothing can be tapped in my whole app anymore. Like the stop button on the first TabItem.

Any help is greatly appreciated!

Steven-Carrot
  • 2,368
  • 2
  • 12
  • 37
Dince-afk
  • 196
  • 7
  • Make a custom one https://stackoverflow.com/questions/72496023/adding-animation-to-tabviews-in-swiftui-when-switching-between-tabs/72816878#72816878 – lorem ipsum Jul 28 '22 at 17:22

3 Answers3

1

Using selection and onChange of the TabView.

Try this code below, it may be what you needed:

struct ContentView: View {
@State var selection = "A"
@State var isDisable = false
var body: some View {
    TabView(selection: $selection) {
        VStack {
            Button {
                isDisable.toggle()
            } label: {
                Text("View A")
                Text("DISABLE B & C ? = \(String(isDisable))")
                    .foregroundColor(.red)
            }
        }
        .tabItem {
            Image(systemName: "note")
        }
        .tag("A")
        
        Text("View B")
            .tabItem {
                Image(systemName: "note")
            }
            .tag("B")
        
        Text("View C")
            .tabItem {
                Image(systemName: "note")
            }
            .tag("C")
    }
    .onChange(of: selection) { newValue in
        if isDisable {
            selection = "A"
        }
    }
  }
}
Steven-Carrot
  • 2,368
  • 2
  • 12
  • 37
  • Am I missing something? Because either in my project as well as when I copy your answer, it doesn't work. Meaning I can still tap and go wherever I want. My environment is Xcode 14 beta 3 and iOS 16. Does anyone have an idea? Does the code work for your? – Dince-afk Jul 29 '22 at 18:49
  • This is provided modifiers by SwiftUI, so I think it should run normally everywhere. I have Xcode 14, iOS16. – Steven-Carrot Jul 29 '22 at 18:55
  • Did you click on “disable button” in first view before trying to navigate to another view? – Steven-Carrot Jul 29 '22 at 18:56
  • Yes, I think so. Might be something I'm missing... I'm actually stuck on this way too long, and I'm not thinking clearly anymore. But thanks anyway! – Dince-afk Jul 29 '22 at 18:58
  • Oh one more tip. If you use tag(Int value), it would not work too. Hope you did use tag(String value) of mine. You are welcome Happy coding. – Steven-Carrot Jul 29 '22 at 18:59
  • 1
    It did work on my physical iPhone! No idea why. I'm sure I'll find out why soon enough. Thanks so much! – Dince-afk Jul 29 '22 at 19:17
0

The only thing I can think of is selecting the desired tab when your desired condition is met. Something like this:

final class ContentViewModel: ObservableObject {
    @Published var selection = 0 {
        didSet {
            if oldValue == 0 && selection != 0 {
                selection = 0
            }
        }
    }
}

struct ContentView: View {
    @StateObject var viewModel = ContentViewModel()

    var body: some View {
        TabView(selection: $viewModel.selection) {
            View1()
                .tabItem {
                    Label("Meditate", systemImage: "timer")
                }
                .tag(0)
            
            View2()
                .tabItem {
                    Label("Sessions", systemImage: "list.bullet")
                }
                .tag(1)

            View3()
                .tabItem {
                    Label("Settings", systemImage: "gearshape")
                }
                .tag(3)
        }
    }
}
narek.sv
  • 845
  • 5
  • 22
0

I think I actually found a potential solution. I think it will work for me. I put the conditional TabItem views into an if statement. When the condition is true, they disappear, leaving only a tab bar view the desired sinlge TabItem.

TabView(selection: $tabSelected) {
            MeditationTimer(vm: vm, isDisable: $isDisable)
                .tabItem({
                    Label("Meditate", systemImage: "timer")
                })
                .tag(0)
            if !vm.isActive {
                History(vm: vm)
                    .tabItem {
                        Label("Sessions", systemImage: "list.bullet")
                    }
                    .tag(1)
                    
                Settings(vm: vm)
                    .tabItem {
                        Label("Settings", systemImage: "gearshape")
                    }
                    .tag(2)
            }
        }
Dince-afk
  • 196
  • 7