How to Use TabView of SwiftUI

Setting multiple tabbars in UIKit requires UITabBarController. But it’s implemented through TabView in the SwiftUI.

In this Article we will also introduce how to hide TabBar when view pushed.

Demo Download.zip

In this Demo with other Codes, I’m also learning SwiftUI, in the ContentView, you can change code like this to see my Project Demo.

1
2
3
4
5
6
7
8
struct ContentView: View {
    var body: some View {
        RootView()
//        NavigationView {
//            TabBarController()
//        }
	}
}
TabBar Animation
img
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import SwiftUI

struct TabBarContentView: View {
    
    @State private var selectedTab = 0
    
    var body: some View {
        ZStack(alignment: .bottom) {
            TabView(selection: $currTab) {
                HomeView()
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .tag(TabEnum.home)
                ToolView()
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .tag(TabEnum.tool)
                TimerView()
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .tag(TabEnum.timer)
                MyView()
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .tag(TabEnum.my)
            }
                TabBarView(selectedTab: $currTab, safeEdgeInsets: proxy.safeAreaInsets)
        }
//            .safeAreaInset(edge: .bottom) {
//                Color.green.frame(height: 80)
//            }
//            .safeAreaInset(edge: .top) {
//                Color.green.frame(height: 104)
//            }

    }
}

TabBarView

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import SwiftUI

struct TabBarView: View {
    
    @Binding var selectedTab: TabEnum
    var safeEdgeInsets: EdgeInsets
    
    var body: some View {
        VStack {
            Spacer()
            HStack {
                content
            }
            .padding(12)
            .background(Color(.black).opacity(0.8))
            .background(.ultraThinMaterial)
            .mask(RoundedRectangle(cornerRadius: 24, style: .continuous))
			  .shadow(color: .red.opacity(0.8), radius: 20, x: 0, y: 20)
            .overlay(
                RoundedRectangle(cornerRadius: 24, style: .continuous)
                    .stroke(.linearGradient(colors: [.white.opacity(0.5), .white.opacity(0)], startPoint: .topLeading, endPoint: .bottomTrailing))
            )
            .padding(.horizontal, 24)
        }
        .padding(.bottom, safeEdgeInsets.bottom == 0 ? 20 : safeEdgeInsets.bottom + 10)
    }
    
    var content: some View {
        
        ForEach(tabItems) { item in
            Button {
                withAnimation {
                    selectedTab = item.tab
                }
            } label: {
                Image(systemName: item.icon)
                    .frame(height: 36)
                    .foregroundColor(.white)
                    .opacity(selectedTab == item.tab ? 1 : 0.5)
                    .background(
                        VStack {
                            RoundedRectangle(cornerRadius: 2)
                                .fill(Color.accentColor)
                                .frame(width: selectedTab == item.tab ? 30 : 0, height: 4)
                                .offset(y: -4)
                                .opacity(selectedTab == item.tab ? 1 : 0)
                            Spacer()
                        }
                    )
            }
            //  tabBarItem Equal width
            .frame(maxWidth: .infinity)
        }
    }
}

struct TabBarView_Previews: PreviewProvider {
    static var previews: some View {
        TabBarView(selectedTab: .constant(.home), safeEdgeInsets: EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
    }
}

struct TabItem: Identifiable {
    var id = UUID()
    var icon: String
    var tab: TabEnum
}

var tabItems = [
    TabItem(icon: "house", tab: .home),
    TabItem(icon: "bag.badge.plus", tab: .tool),
    TabItem(icon: "alarm.waves.left.and.right", tab: .timer),
    TabItem(icon: "person", tab: .my),
]

enum TabEnum: String {
    case home
    case tool
    case timer
    case my
}

Hide TabBar

TabBar needs to be hidden when navigation from one page to the next interface. But the esisting SwiftUI doesn’t directly provide a method to hide TabBar. If the root view is a tabView, the tabBar will not be actively hidden when jumping to the next interface, So we need wrap TabView directly with NavigationView.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import SwiftUI

struct ContentView: View {
    var body: some View {
    	  // ⭐️⭐️⭐️: if you use NavigationStack in the Project, please note here.
		  // iOS 16, iPadOS 16, macOS 13, tvOS 16, or watchOS 9
        if #available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *) {
            NavigationStack {
                TabBarController()
            }
        } else {
            NavigationView {
                TabBarController()
            }
        }
    }
}
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy