Search code examples
swiftswiftuiscrollviewtabview

ScrollView overlaps Text in VStack when hiding TabBar


Currently I'm developing a multi-tab app, therefore the ContentView consists of a TabView. In the linked SecondView I want to hide the TabBar but when doing this, the contents of the ScrollView are overlapping with the content of the surrounding VStack below it.

The following code is a simplified and abstracted code of the app:

struct ContentView: View {
    
    static var tabBar: UITabBar!
    
    var body: some View {
        TabView {
            NavigationView {
                NavigationLink(destination: SecondView()) {
                    Text("Navigate")
                }
            }
            .tabItem { EmptyView() }
        }
    }
}

struct SecondView: View {
    var body: some View {
        VStack {
            ScrollView {
                ForEach(0..<50) { idx in
                    Text("\(idx)")
                }
            }
            Text("Just some text so visualize the overlapping")
        }
        .padding(.bottom, 30)
        .onAppear {
            ContentView.tabBar.isHidden = true
        }
        .padding(.bottom, -ContentView.tabBar.frame.height)
    }
}

extension UITabBar {
    override open func didMoveToSuperview() {
        super.didMoveToSuperview()
        ContentView.tabBar = self
    }
}

To be more precise this starts happening after I apply the negative padding to the VStack in order to make the free space usable.

Does anyone have an idea on how to fix this?


Solution

  • It is because by default Text view is transparent, so you just see scroll view content below it.

    Here is a demo of possible solution

    demo

    VStack {
        ScrollView {
            ForEach(0..<50) { idx in
                Text("\(idx)")
            }
        }
        Text("Just some text so visualize the overlapping")
            .padding()
            .frame(maxWidth: .infinity)
            .background(Color(UIColor.systemBackground))
            .edgesIgnoringSafeArea(.bottom)
    }
    

    Another possible alternate is to clip ScrollView content

    demo

    ScrollView {
        ForEach(0..<50) { idx in
            Text("\(idx)")
        }
    }
    .clipped()