0
votes

My app has 3 tabs (Read, Discover, Profile). In one specific view that is navigated to from the the Read view, I want to hide the tab view and show a custom toolbar/tab bar that will show action buttons (e.g, save, like).

I have been Googling and searching Stack Overflow for 2 days and no luck. This is what I've seen / tried:

  • Hide tab view: Seems like this is simply not possible with SwiftUI. There are a few hacks posted on this site but they don't work for me (e.g., try use UITabBarController modifications) or too compromised (e.g., wrap tab view in navigation view which results in tab view disappearing in all sub views)
  • Use root page: This works, but then navigation view breaks (can't get back button back)
  • Conditional tab view: I didn't see this posted anywhere, but gave it a go. I tried an if statement in the tab view with a bool state variable, where the main tabs (Read, Discover, Profile) are set to default, and on the specific sub view page, a different tab view is used (e.g, with Save buttons). But that also doesn't seem to work.

Anyone have ideas or examples of working code? Thanks!

2
Thanks, although some specific feedback would be appreciated on how the question could be improved as this is my first time posting. If it is because I didn’t include code, the guidance is pretty clear that code is not a requirement. Or is it? - deanseg
Thanks! That’s clear - I’ll add reproducible code shortly. - deanseg

2 Answers

1
votes

I have implemented two solutions in the code below:

  1. Update tabs on the go
  2. Go to a specific view on tab
enum MyTab: String {
    case a, b, c, d

    var view: AnyView {
        switch self {
        case .a, .b: return AnyView(ChildView(page: rawValue))
        case .c, .d: return AnyView(SpecificView())
        }
    }
}

class ViewModel: ObservableObject {

    @Published var tabs: [MyTab] = [.a, .b]
    @Published var selectedTab: MyTab = .a
    @Published var shouldShowTab = true

    var customBinding: Binding<MyTab> {
        Binding(get: {
            self.selectedTab
        }, set: {
            if $0 == .c {
                // save
            } else if $0 == .d {
                // like
            }
            self.selectedTab = $0
        })
    }

    func updateTabs() {
        tabs = [.c, .d]
    }
}

struct ContentView: View {

    @EnvironmentObject var viewModel: ViewModel

    var body: some View {
        Group {
            if viewModel.shouldShowTab {
                TabView(selection: viewModel.customBinding) {
                    ForEach(viewModel.tabs, id: \.self) { tab in
                        tab.view
                            .tabItem { Text(tab.rawValue) }
                    }
                }
            } else {
                SpecificView()
            }
        }
    }
}

struct ChildView: View {

    @EnvironmentObject var viewModel: ViewModel
    var page: String

    var body: some View {
        VStack(spacing: 24) {
            Text("Page: \(page)")
            Button(action: {
                self.viewModel.shouldShowTab = false
            }) {
                Text("Go to Specific View")
            }
            Button(action: {
                self.viewModel.updateTabs()
            }) {
                Text("or update tabs on the go")
            }
        }
    }
}

struct SpecificView: View {

    @EnvironmentObject var viewModel: ViewModel

    var body: some View {
        // Use whatever you'd like tab etc.
        VStack(spacing: 24) {
            Text("My Specific View")
            Button(action: {
                self.viewModel.shouldShowTab = true
            }) {
                Text("Go back to Tab View")
            }
        }
    }
}
0
votes

You can show your new view as a Sheet, that way the specific view you mentioned can have its own TabView.

struct ContentView: View {

    @State var presentView = false

    var body: some View {
        Button(action: {
            self.presentView.toggle()
        }) {
            Text("Present View")
        }
        .sheet(isPresented: $presentView) {
            TabView {
                // content
            }
        }
    }
}