Non-translucent UITabBar creates strange grey bar

Viewed 717

Using SwiftUI, I have several NavigationViews nested inside a TabBar. The reason for this is that I would like to change the title of each NavigationView to reflect the selected tab, and I can't find another way to do this. Also, it is very important to my client that the background color of the UITabBar be solid white. For this reason I set UITabBar.appearance().isTranslucent = false, otherwise it appears grey. However, as soon as I do this, I see a strange grey line above the UITabBar. How can I get rid of this?

struct ContentView: View {
    
    init() {
            
        UITabBar.appearance().backgroundColor = UIColor.white
        UITabBar.appearance().isTranslucent = false
    }
    
    var body: some View {
        TabView {

        NavigationView {
            
            Text("First tab")
                .padding(10)
                .background(Color.white)
                .navigationBarTitle(Text("First tab"), displayMode: .inline)
        }
        .tabItem {
            Text("First tab")
        }
            
        NavigationView {
            
            Text("Second tab")
                .padding(10)
                .background(Color.white)
                .navigationBarTitle(Text("Second tab"), displayMode: .inline)
        }
        .tabItem {
            Text("Second tab")
        }
        }
    }
}

Grey bar above TabBar

2 Answers

As another alternative to the options in Asperi's answer, you can replace these lines of code:

UITabBar.appearance().backgroundColor = UIColor.white
UITabBar.appearance().isTranslucent = false

with these:

let tabBarAppearance = UITabBarAppearance()
tabBarAppearance.configureWithOpaqueBackground()
tabBarAppearance.backgroundColor = UIColor.white
UITabBar.appearance().standardAppearance = tabBarAppearance

It has the same effect, but using configureWithOpaqueBackground() instead of setting isTranslucent to false preserves the constraints that NavigationView is relying on.

This

        UITabBar.appearance().isTranslucent = false

is a hack (non-documented assumption about TabView internal implementation) that breaks NavigationView layout (removes view to which NavigationView has active constraints)

Here are possible workarounds:

  1. use only one root NavigationView

demo

struct ContentView: View {

    init() {

        UITabBar.appearance().backgroundColor = UIColor.white
        UITabBar.appearance().isTranslucent = false
    }

    @State private var title = ""
    var body: some View {

        NavigationView {
            TabView {

                Text("First tab")
                    .padding(10)
                    .background(Color.white)
                    .onAppear {
                        self.title = "First tab"
                    }
                    .tabItem {
                        Text("First tab")
                }

                Text("Second tab")
                    .padding(10)
                    .background(Color.white)
                    .onAppear {
                        self.title = "Second tab"
                    }
                    .tabItem {
                        Text("Second tab")
                }
            }
            .navigationBarTitle(Text(title), displayMode: .inline)
        }
    }
}
  1. Create custom tab bar (using HStack of Button views)
Related