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

Popular posts from this blog

Using Core ML with SwiftUI: Build an AI-Powered App

CI/CD for iOS Projects with Xcode: A Complete Guide

Dependency Injection in iOS with SwiftUI