2

I'm learning SwiftUI and I encountered a problem while trying to build an app. My question is how can I make a tab bar that changes a systemImage while active (when the home button is active it shows "home.fill", and when the user presses the search button, the home button changes to "home").

import SwiftUI

struct ContentView: View {
    
    @State private var fullScreenCover = false
    
    init() {
        UITabBar.appearance().isTranslucent = false
    }
    
    var body: some View {
        
        VStack {
            ForEach(0..<6) { num in
                Spacer()
            }
            
            HStack {
                Spacer()
                Button(action: {}, label: {
                    Image(systemName: "message")
                    .font(.system(size: 20))
                })
                .padding(.horizontal, 15)
            }
            .foregroundColor(Color("Reverse"))
            .padding(.vertical, 8)
            
            TabView {
                Main_Home()
                .tabItem {
                    Image(systemName: "house")
                    .font(.system(size: 30))
                }
                
                Main_Search()
                .tabItem {
                    Image(systemName: "magnifyingglass")
                    .font(.system(size: 30))
                }
                
                Main_AddContent()
                .tabItem {
                    Image(systemName: "plus.viewfinder")
                    .font(.system(size: 30))
                }
                
                Main_Message()
                .tabItem {
                    Image(systemName: "pencil.circle.fill")
                    .font(.system(size: 30))
                }
                
                Main_Profile()
                .tabItem {
                    Image(systemName: "person.crop.circle")
                    .font(.system(size: 30))
                }
            }
            .accentColor(Color("Reverse"))
            
        }
        .background(Color("Normal"))
        .edgesIgnoringSafeArea(.all)
    }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
AnyOne
  • 21
  • 3

1 Answers1

0

Here is a custom ViewModifier that you can use for adding tab items:

public struct TabViewItem<SelectionValue>: ViewModifier where SelectionValue: Hashable {
    @Binding private var selectedIndex: SelectionValue
    private let index: SelectionValue
    private let text: String
    private let imageName: String

    public init(selectedIndex: Binding<SelectionValue>, index: SelectionValue, text: String, imageName: String) {
        self._selectedIndex = selectedIndex
        self.index = index
        self.text = text
        self.imageName = imageName
    }

    public func body(content: Content) -> some View {
        content
            .tabItem {
                image
                Text(text)
            }
            .tag(index)
    }

    private var image: some View {
        guard selectedIndex == index else {
            return Image(systemName: imageName)
        }
        let imageName = self.imageName + ".fill"
        if let uiImage = UIImage(systemName: imageName) {
            return Image(uiImage: uiImage)
        }
        return Image(systemName: self.imageName)
    }
}
public extension View {
    func tabItem<Selection>(
        _ text: String,
        imageName: String,
        index: Selection,
        selection: Binding<Selection>
    ) -> some View where Selection: Hashable {
        modifier(TabViewItem(selectedIndex: selection, index: index, text: text, imageName: imageName))
    }
}

Then, creating the TabView is more straightforward:

struct ContentView: View {
    @State private var selectedTab = 3

    var body: some View {
        TabView(selection: $selectedTab) {
            Text("Main_Home")
                .tabItem("Home", imageName: "house", index: 1, selection: $selectedTab)
            Text("Main_Search")
                .tabItem("Search", imageName: "magnifyingglass", index: 2, selection: $selectedTab)
            Text("Main_AddContent")
                .tabItem("AddContent", imageName: "plus.viewfinder", index: 3, selection: $selectedTab)
            Text("Main_Message")
                .tabItem("Message", imageName: "pencil.circle", index: 4, selection: $selectedTab)
            Text("Main_Profile")
                .tabItem("Profile", imageName: "person.crop.circle", index: 5, selection: $selectedTab)
        }
    }
}

Note: The above implementation is for generic purposes - if you don't need some parts (like text in tabs) just remove it or make them optional.

pawello2222
  • 46,897
  • 22
  • 145
  • 209