xcodeswiftuiios15

ios - TabView in SwiftUI loses background when content of the NavigationView is too short


Having the code of my very simple SwiftUI app attached, I'm struggling with a visual issue:

  1. When navigating between pages inside of a TabView, the tab bar in the bottom has a nice translucent background and navigating forth and back is looking nice - if the subpages are taller than the screen size:

correct

  1. When the second page (DetailView) has a content that is shorter than the screen size, the tab bar's background disappears and that causes a very annoying overlap effect when navigating back:

incorrect

Is there a solution for this in SwiftUI, iOS 15?

Code:

import SwiftUI

struct ContentView: View {
    @State private var isDetailActive = false

    var body: some View {
        TabView {
            NavigationView {
                ScrollView {
                    VStack {
                        Text("Custom title")
                            .frame(maxWidth: .infinity)
                            .padding(20)
                            .background(Color(red: 0.1, green: 0.1, blue: 0.1))
                    }

                    ForEach(1..<50) {_ in
                        NavigationLink(destination: DetailView(isVisible: $isDetailActive), isActive: $isDetailActive) {
                            Text("Hello, world!")
                                .padding(10)
                        }
                    }
                }
                .navigationBarHidden(true)
                .navigationTitle("Navigation title")
            }
            .tabItem {
                Image(systemName: "house")
                Text("Test")
            }
        }
    }
}

struct DetailView: View {
    @Binding var isVisible: Bool

    var body: some View {
        ScrollView {
            VStack {
                Button(action: {
                    isVisible = false
                }) {
                    Text("Back")
                        .frame(maxWidth: .infinity)
                        .padding(20)
                        .background(Color(red: 0.1, green: 0.1, blue: 0.1))
                }

                ForEach(0..<10) { item in       // <-- change this to 20 to simulate a larger page
                    Text("Text")
                        .padding(10)
                }
            }
        }
        .navigationBarHidden(true)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .colorScheme(.dark)
    }
}

Solution

  • iOS 15 changed the default look of the TabBar when there is nothing underneath it to scroll.

    A work-around that worked for me is modifying the TabBar in an onAppear statement:

    TabView {
        ...
    }
    .onAppear {
        let tabBarAppearance = UITabBarAppearance()
        tabBarAppearance.configureWithDefaultBackground()
        UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
    }