2

Hello I have created a custom tab bar in swift ui that contains 6 tabs each embedded in a nivation view. When I select the 5th or 6th tabs I see a "more" button at the top. Which is almost like the back button for navigation links. How can I remove this? I tried using navigationbarbackbuttonhidden(true) and that didn't work. I also tried adding .toolbar(.hidden, for: .tabbar) onto my tabView and this did not work also. I would appreciate any help to get ride of that button. Thanks.

import SwiftUI
import Combine
import MapKit

struct MainTabView: View {
    @State private var selectedTab = 0
    @EnvironmentObject var pop: PopToRoot
    @Namespace var animation

init() {
    UITabBar.appearance().isHidden = true
}
    var body: some View {
        TabView(selection: $selectedTab){
            NavigationView(){
                FeedView()
            }.tag(1)
            NavigationView(){
                JobsView()
            }.tag(2)
            NavigationView(){
                ExploreView()
            }.tag(3)
            NavigationView(){
                QuestionView()
            }.tag(4)
            NavigationView(){
                MessagesHomeView()
            }.tag(5)
            NavigationStack {
                ProfileView()
            }.tag(6)
        }
        .overlay (
            HStack {
                TabBarButton(change: $selectedTab, title: "Home", index: 1, image: selectedTab == 1 ? "h.circle.fill" : "h.circle", animation: animation)
                TabBarButton(change: $selectedTab, title: "Jobs/Shop", index: 2, image: "", animation: animation)
                TabBarButton(change: $selectedTab, title: "Explore", index: 3, image: "magnifyingglass", animation: animation)
                TabBarButton(change: $selectedTab, title: "Ask", index: 4, image: "questionmark", animation: animation)
                TabBarButton(change: $selectedTab, title: "Messages", index: 5, image: selectedTab == 5 ? "message.fill" : "message", animation: animation)
                TabBarButton(change: $selectedTab, title: "Profile", index: 6, image: selectedTab == 6 ? "person.crop.circle.fill" : "person.crop.circle", animation: animation)
            }
            , alignment: .bottom
        )
    }
}

struct TabBarButton: View {
    @Binding var change: Int
    var title: String
    var index: Int
    var image: String
    var animation: Namespace.ID
    @EnvironmentObject var popRoot: PopToRoot
    var body: some View{
        Button {
            change = index
            withAnimation {
                popRoot.tab = index
            }
        } label: {
            VStack {
                Image(systemName: image).font(.title2)
                Text(title).font(.system(size: 10))
            }
            .foregroundColor(popRoot.tab == index ? .orange : .primary.opacity(0.5))
            .frame(maxWidth: .infinity)
            .overlay (
                ZStack {
                    if popRoot.tab == index {
                        TabIndicator()
                            .fill(.orange.gradient)
                            .matchedGeometryEffect(id: "TAB", in: animation)
                            .padding(.top, -9)
                            .padding(.horizontal, 8)
                    }
                }
            )
        }
    }
}

struct TabIndicator: Shape {
    func path(in rect: CGRect) -> Path {
        let newRect = CGRect(x: rect.origin.x, y: rect.origin.y, width: rect.width, height: 3)
        return Path { path in
            path.addRect(newRect)
        }
    }
}
ahmed
  • 341
  • 2
  • 9

2 Answers2

1

Check first if you can replace the toolbar (which has the "More" button) with an empty view.

First, define a custom extension or view, possibly something like this:

extension View {
    static var hidden: some View {
        EmptyView()
    }
}

Then, since navigationBarItems(leading:trailing:) is deprecated, use toolbar(content:) with [navigationBarLeading]https://developer.apple.com/documentation/swiftui/toolbaritemplacement/navigationbarleading) or navigationBarTrailing placement.

struct MainTabView: View {
    @State private var selectedTab = 0
    @EnvironmentObject var pop: PopToRoot
    @Namespace var animation

    init() {
        UITabBar.appearance().isHidden = true
    }
    
    var body: some View {
        TabView(selection: $selectedTab){
            NavigationView(){
                FeedView()
            }
            .tag(1)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) { EmptyView() }
            }

            NavigationView(){
                JobsView()
            }
            .tag(2)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) { EmptyView() }
            }

            NavigationView(){
                ExploreView()
            }
            .tag(3)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) { EmptyView() }
            }

            NavigationView(){
                QuestionView()
            }
            .tag(4)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) { EmptyView() }
            }

            NavigationView(){
                MessagesHomeView()
            }
            .tag(5)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) { EmptyView() }
            }

            NavigationStack {
                ProfileView()
            }
            .tag(6)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) { EmptyView() }
            }
        }
        .overlay (
            HStack {
                TabBarButton(change: $selectedTab, title: "Home", index: 1, image: selectedTab == 1 ? "h.circle.fill" : "h.circle", animation: animation)
                TabBarButton(change: $selectedTab, title: "Jobs/Shop", index: 2, image: "", animation: animation)
                TabBarButton(change: $selectedTab, title: "Explore", index: 3, image: "magnifyingglass", animation: animation)
                TabBarButton(change: $selectedTab, title: "Ask", index: 4, image: "questionmark", animation: animation)
                TabBarButton(change: $selectedTab, title: "Messages", index: 5, image: selectedTab == 5 ? "message.fill" : "message", animation: animation)
                TabBarButton(change: $selectedTab, title: "Profile", index: 6, image: selectedTab == 6 ? "person.crop.circle.fill" : "person.crop.circle", animation: animation)
            }
            , alignment: .bottom
        )
    }
}

The toolbar(content:) modifier places an EmptyView() on the leading position of the navigation bar for each NavigationView, which should have the effect of removing the "More" button or any other leading items on the navigation bar.


This did not work. I can still see the more button at the top of the screen. Any thoughts?

Another approach would be, since you're already using a custom tab bar UI, to bypass TabView for the custom tab bar altogether.

You could hold all the views in an array and show the currently selected one using a conditional statement.
And then use your custom tab bar UI to change the currently selected view.

import SwiftUI
import Combine
import MapKit

struct MainTabView: View {
    @State private var selectedTab = 0
    @EnvironmentObject var pop: PopToRoot
    @Namespace var animation
    
    private var tabs: [AnyView] = [
        AnyView(NavigationView() { FeedView() }),
        AnyView(NavigationView() { JobsView() }),
        AnyView(NavigationView() { ExploreView() }),
        AnyView(NavigationView() { QuestionView() }),
        AnyView(NavigationView() { MessagesHomeView() }),
        AnyView(NavigationStack { ProfileView() })
    ]

    var body: some View {
        VStack {
            if selectedTab < tabs.count {
                tabs[selectedTab]
            }
            
            Spacer()
            
            HStack {
                TabBarButton(change: $selectedTab, title: "Home", index: 0, image: selectedTab == 0 ? "h.circle.fill" : "h.circle", animation: animation)
                // Your other TabBarButtons
            }
            .background(Color.white.shadow(radius: 2))
        }
    }
}

// Your other structures

This way, you bypass the default behavior of TabView and control the view being displayed using your custom tab bar.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks for the answer but this did not work. I can still see the more button at the top of the screen. Any thoughts? – ahmed Aug 20 '23 at 03:40
  • @ahmed OK, I have edited the answer to propose an alternative approach. – VonC Aug 20 '23 at 12:17
  • maybe your even an expert with this: https://stackoverflow.com/questions/76981945/swift-ui-image-does-not-drag-correctly-when-zoomed-in – ahmed Aug 26 '23 at 07:25
0

You can't do this with SwifUI main framework, you must redefine the navigation bar!

Mohab
  • 15
  • 6
  • Yes I did create a custom tab bar and I am still encountering this issue. I'll add in my code to display what I did. Can you elaborate on your answer, – ahmed Aug 19 '23 at 17:36