How to Build a Custom Tab Bar in SwiftUI
A well-designed tab bar enhances user navigation and improves the overall user experience. While SwiftUI provides a default TabView, creating a custom tab bar allows for greater flexibility and a unique design. In this blog, we’ll build a fully customizable tab bar in SwiftUI with animations and active state highlighting.
1. Setting Up the Custom Tab Bar Structure
The first step is to define a structure for our custom tab bar. We’ll use an enum to manage tab selections.
Define the Tab Enum
enum Tab: String, CaseIterable {
case home = "house"
case search = "magnifyingglass"
case profile = "person"
}Here, we define three tabs: Home, Search, and Profile, each associated with an SF Symbol for the icon.
2. Creating the Custom Tab Bar Component
Now, let’s build a custom tab bar with dynamic tab selection.
CustomTabBar View
struct CustomTabBar: View {
@Binding var selectedTab: Tab
var body: some View {
HStack {
ForEach(Tab.allCases, id: \ .self) { tab in
Spacer()
VStack {
Image(systemName: tab.rawValue)
.font(.system(size: 22))
.foregroundColor(selectedTab == tab ? .blue : .gray)
.scaleEffect(selectedTab == tab ? 1.2 : 1.0)
.animation(.spring(), value: selectedTab)
}
.onTapGesture {
selectedTab = tab
}
Spacer()
}
}
.padding(.top, 10)
.frame(height: 60)
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 20))
.padding(.horizontal, 16)
}
}Breakdown of Features:
✅ Uses SF Symbols for tab icons π¨
✅ Highlights the active tab using color and size changes ✨
✅ Smooth scale effect animations when switching tabs π₯
✅ Background blur effect using .ultraThinMaterial
3. Integrating the Tab Bar into the Main View
Now, let’s integrate our custom tab bar with content views.
Main View with Tab Bar Integration
struct ContentView: View {
@State private var selectedTab: Tab = .home
var body: some View {
VStack {
Spacer()
// Dynamic View Switching
switch selectedTab {
case .home:
HomeView()
case .search:
SearchView()
case .profile:
ProfileView()
}
Spacer()
CustomTabBar(selectedTab: $selectedTab)
}
.edgesIgnoringSafeArea(.bottom)
}
}4. Creating Sample Views for Tabs
For a complete demo, we need simple views for each tab.
struct HomeView: View {
var body: some View {
Text("π Home View")
.font(.largeTitle)
.bold()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.white)
}
}
struct SearchView: View {
var body: some View {
Text("π Search View")
.font(.largeTitle)
.bold()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.white)
}
}
struct ProfileView: View {
var body: some View {
Text("π€ Profile View")
.font(.largeTitle)
.bold()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.white)
}
}5. Adding Custom Animations (Optional)
Want an even smoother user experience? Add a subtle fade animation when switching tabs.
Modify ContentView like this:
var body: some View {
VStack {
Spacer()
ZStack {
if selectedTab == .home {
HomeView()
.transition(.opacity)
} else if selectedTab == .search {
SearchView()
.transition(.opacity)
} else if selectedTab == .profile {
ProfileView()
.transition(.opacity)
}
}
.animation(.easeInOut, value: selectedTab)
Spacer()
CustomTabBar(selectedTab: $selectedTab)
}
}✅ Smooth fade animation when switching tabs π
✅ ZStack ensures proper layering of views
Conclusion
We have successfully built a fully functional and customizable tab bar in SwiftUI! π This approach provides:
✔️ Custom styling and animations π¨
✔️ Smooth transitions between views ✨
✔️ Scalability — you can easily add more tabs π
π Happy Coding! π

Comments
Post a Comment