
https://medium.com/geekculture/custom-tabbar-in-swiftui-4d239410ee73
import SwiftUI | |
struct HomeView: View { | |
var body: some View { | |
Text("HomeView") | |
} | |
} | |
struct FavoriteView: View { | |
var body: some View { | |
Text("FavoriteView") | |
} | |
} | |
struct NewsView: View { | |
var body: some View { | |
Text("NewsView") | |
} | |
} | |
struct ProfileView: View { | |
var body: some View { | |
Text("ProfileView") | |
} | |
} | |
struct ContentView: View { | |
@State var selectedIndex = 0 | |
var body: some View { | |
ZStack(alignment: .bottom) { | |
TabView(selection: $selectedIndex) { | |
HomeView() | |
.tag(TabbarItem.home.rawValue) | |
FavoriteView() | |
.tag(TabbarItem.favorite.rawValue) | |
NewsView() | |
.tag(TabbarItem.news.rawValue) | |
ProfileView() | |
.tag(TabbarItem.profile.rawValue) | |
} | |
.frame(width: CGFloat((80 * (TabbarItem.allCases.count - 1)) + 120)) | |
.padding(.vertical, 26) | |
ZStack { | |
HStack { | |
ForEach(TabbarItem.allCases, id: \.self) { item in | |
Button { | |
selectedIndex = item.rawValue | |
} label: { | |
tabItemView(tabbarItem: item, isActive: selectedIndex == item.rawValue) | |
} | |
} | |
} | |
.padding(6) | |
} | |
.frame(height: 70) | |
.background(.blue.opacity(0.2)) | |
.cornerRadius(15) | |
.padding(.vertical, 26) | |
} | |
} | |
} | |
extension ContentView { | |
func tabItemView(tabbarItem: TabbarItem, isActive: Bool) -> some View { | |
HStack { | |
Spacer() | |
Image(systemName: tabbarItem.iconName) | |
.resizable() | |
.renderingMode(.template) | |
.foregroundColor(isActive ? .black : .gray) | |
.frame(width: 20, height: 20) | |
if let title = tabbarItem.title, isActive { | |
Text(title) | |
.lineLimit(1) | |
.font(.system(size: 14)) | |
.foregroundColor(isActive ? .black : .gray) | |
} | |
Spacer() | |
} | |
.frame(width: isActive ? 120 : 80, height: 60) | |
.background(isActive ? .blue.opacity(0.4) : .clear) | |
.cornerRadius(10) | |
} | |
} | |
enum TabbarItem: Int, CaseIterable { | |
case home | |
case favorite | |
case news | |
case profile | |
var title: String? { | |
switch self { | |
case .home: | |
return "Home" | |
case .favorite: | |
return "Favorite" | |
case .news: | |
return "News" | |
case .profile: | |
return nil | |
} | |
} | |
var iconName: String { | |
switch self { | |
case .home: | |
return "house" | |
case .favorite: | |
return "heart" | |
case .news: | |
return "newspaper" | |
case .profile: | |
return "person.crop.circle" | |
} | |
} | |
} |