I have a SwiftUI setup where I'm using a TabView for navigation between different views. In larger screen sizes (width > 900), I've implemented a side menu using an HStack to provide a more convenient way of switching tabs. However, in this setup, I want to hide the tab bar that's normally used for navigation between tabs, while still keeping the tab navigation functional.
Here's a simplified version of my code:
// Other code...
var body: some View {
GeometryReader { geometry in
HStack(spacing: 0) {
if geometry.size.width > 900 {
// Side menu implementation...
}
TabMenuView(activeTab: $route)
.frame(maxWidth: .infinity)
.toolbar(.hidden, for: .tabBar) // This only works, outside the root of a nvaigation stack
}
}
}
}
struct TabMenuView: View {
// Other code...
var body: some View {
TabView(selection: $activeTab) {
// Tab items...
}
}
}
I tried a lot, but I just can't hide the TabBar, without hiding the whole TabView.
It work's, when a view is pushed to a NavigationStack with the .toolbar(.hidden, for: .tabBar)
, but thats not the behavior I am hoping for.
You should maintain the selected tab and use bindings where both UI versions depend on, respectively set it:
import SwiftUI
struct MainView: View {
enum Tabs: String {
case one
case two
}
// @Environment(\.horizontalSizeClass) var horizontalSizeClass
@State private var tabSelection: Tabs = .two
var body: some View {
GeometryReader { geometry in
if geometry.size.width <= 900 {
TabView(selection: $tabSelection) {
ContentView()
.tabItem {
Label(Tabs.one.rawValue, systemImage: "1.square")
}
.tag(Tabs.one.rawValue)
OtherView()
.tabItem {
Label(Tabs.two.rawValue, systemImage: "2.square")
}
.tag(Tabs.two.rawValue)
}
} else {
// use Custom Menu
VStack {
switch tabSelection {
case .one:
HStack {
Button("Show Tab 2") {
tabSelection = .two
}
Spacer()
ContentView()
}
case .two:
HStack {
Button("Show Tab 1") {
tabSelection = .one
}
Spacer()
OtherView()
}
}
}
}
}
}
}
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
}
}
struct OtherView: View {
var body: some View {
VStack {
Text("Other view")
}
.padding()
}
}
#Preview {
MainView()
}
Note: you may use Size Classes to determine the layout and UI.