Barrrdi
Barrrdi

Reputation: 1171

Background in screens in TabView w/ PageTabViewStyle doesn't fill entire vertical space available

I want a TabView that uses a PageTabViewStyle with each individual screen having a different background colour that fills the entire vertical space available (i.e. extended into the safe areas).

TabView(selection: $selection) {
    VStack {
        Text("screen 1")
    }.frame(maxWidth: .infinity, maxHeight: .infinity)
     .background(Color.green)
    
    VStack {
        Text("screen 2")
    }.frame(maxWidth: .infinity, maxHeight: .infinity)
     .background(Color.red)

}.edgesIgnoringSafeArea(.all)
 .frame(maxWidth: .infinity, maxHeight: .infinity)
 .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))

However, it looks like this:

enter image description here

And after I scroll to the bottom:

enter image description here

The white colour can be changed if I set a background colour for the TabView itself, which would be fine if each screen used the same background colour. Is there any way for individual screens within the TabView to have a unique background colour set that fills the entire screen?

Upvotes: 0

Views: 696

Answers (2)

zdravko zdravkin
zdravko zdravkin

Reputation: 2386

If you are using .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) you can use ZStack to set fullsize background. Update BacgkroundVIEW based on index select of your tabView.

ZStack { BackhroundView() // or color image .ignoresSafeArea()

TabView(selection: $selection) {
    VStack {
        Text("screen 1")
    }.frame(maxWidth: .infinity, maxHeight: .infinity)
  
    
    VStack {
        Text("screen 2")
    }.frame(maxWidth: .infinity, maxHeight: .infinity)
  

}
 .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))

Upvotes: 0

Lineous
Lineous

Reputation: 1782

Normally I wouldn't suggest GeometryReader, but this doesn't look like intended behavior on Apple's part. The key is expanding the background modifier color to a large enough height so that you can't see the white background behind the tab.

Thank you, Asperi, for sharing the link to a similar question for inspiration:

https://stackoverflow.com/a/62596307/12299030

struct ContentView: View {
    
    @State private var selection: Int = 0
    
    var body: some View {
        GeometryReader { geo in
            TabView(selection: $selection) {
                
                VStack {
                    Text("Screen 1")
                }.frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(
                    EmptyView()
                        .frame(minHeight: 2 * geo.size.height)
                        .background(Color.green)
                )
                .tag(0)
                
                VStack {
                    Text("Screen 2")
                }.frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(
                    EmptyView()
                        .frame(minHeight: 2 * geo.size.height)
                        .background(Color.red)
                )
                .tag(1)

            }.edgesIgnoringSafeArea(.all)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
        }
    
    }
    
}

Using an EmptyView combined with a set minimum height of 2 times the current height ensures that the user can scroll up and down, reaching the bounce-back distance, and not see a white background. Put any background you'd like on this view.

You may be able to swap out EmptyView with whatever you'd like, but that was the first thing that came to mind. I added .tag() and selection so that ContentView can be ran on its own in case you'd like to experiment.

Upvotes: 1

Related Questions