Search code examples
swiftuiswiftui-tabview

How to change TabView color for each icon?


I've tried this to try to change the color of the tab icons individually, but for some reason, the color will modify it correctly and then after tapping back to the icon, it will not display the customized color.

How would I go about changing the tab items icons for each individual tab (different colors for each)?

Here's the code for the view holding the TabView that I'm trying to modify.

struct MainView: View {
    @AppStorage("PendingOnboarding") var pendingOnboarding = true

    init() {
        UIPageControl.appearance().currentPageIndicatorTintColor = UIColor(Color.recyclepediaGreen)
    }
    
    var body: some View {
        NavigationView {
            ZStack {
                TabView {
                    CurbsideView()
                        .tabItem {
                            Label("Curbside", systemImage: "car.fill")
                        }
                    ItemsView()
                        .tabItem {
                            Label("Items", systemImage: "archivebox.fill")
                        }
                    LearnView()
                        .tabItem {
                            Label("Learn", systemImage: "info.circle.fill")
                        }
                    ContactUsView()
                        .tabItem {
                            Label("Contact Us", systemImage: "phone.fill.connection")
                        }
                }
                .accentColor(Color.recyclepediaBlue)
                .toolbar {
                    ToolbarItem(placement: .principal) {
                        Image("Recyclepedia")
                            .resizable()
                            .scaledToFit()
                            .padding(.top, 5)
                            .padding(.bottom, 5)
                    }
                }
            }
            .popup(isPresented: $pendingOnboarding, dragToDismiss: false, closeOnTap: false, backgroundColor: Color.white) {
                OnboardingView(pendingOnboarding: $pendingOnboarding)
            }
        }
    }
}

Solution

  • The easiest solution is to use an enum that returns a Color. Like this:

    struct TestTabviewIconColor: View {
        
        @State var pageIndex: TabColor = .red
        
        var body: some View {
            VStack {
                Text("Current page is \(pageIndex.rawValue)")
                TabView(selection: $pageIndex) { // Use the Tabview(selection:) init
                    Text("The First Tab: \(pageIndex.color().description)")
                        .tabItem {
                            Image(systemName: "1.square.fill")
                            Text("First")
                        }
                        .tag(TabColor.red)
                    
                    Text("Another Tab: \(pageIndex.color().description)")
                        .tabItem {
                            Image(systemName: "2.square.fill")
                            Text("Second")
                        }
                        .tag(TabColor.green)
                    
                    Text("The Last Tab: \(pageIndex.color().description)")
                        .tabItem {
                            Image(systemName: "3.square.fill")
                            Text("Third")
                        }
                        .tag(TabColor.teal)
                }
                .accentColor(pageIndex.color())
                .font(.headline)
            }
        }
    }
    
    // Define your enum here
    enum TabColor: Int {
        case red = 0
        case green = 1
        case teal = 2
        
        func color() -> Color {
            switch self {
            case .red:
                return .red
            case .green:
                return .green
            case .teal:
                return .teal
            }
        }
    }
    

    As a bonus, you can select your tab by using it's color simply by calling:

    pageIndex = .green