Home > Mobile >  SwiftUI PageTabViewStyle does not ignore safe area
SwiftUI PageTabViewStyle does not ignore safe area

Time:01-24

I am attempting to implement a PageTabViewStyle inside a NavigationView so that I can swipe between two different lists but the TabView does not ignore the safe area despite having .ignoresSafeArea().

Code

struct TestView: View {
    @State private var selectedPage = 0
    private var pages = [0, 1]
    
    var body: some View {
        NavigationView {
            TabView(selection: $selectedPage) {
                FirstList()
                    .ignoresSafeArea()
                    .tag(0)
                
                SecondList()
                    .tag(1)
            }
            .ignoresSafeArea()
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .principal) {
                    Picker("", selection: $selectedPage) {
                        ForEach(pages, id: \.self) {
                            Text(String($0))
                        }
                    }
                    .scaledToFit()
                    .pickerStyle(.segmented)
                }
            }
        }
    }
}

struct FirstList: View {
    var body: some View {
        List {
            Text("0")
        }
    }
}

struct SecondList: View {
    var body: some View {
        List {
            Text("1")
        }
    }
}

Results:

enter image description here

How do I set it such that the list view would fill the navigationBar like the image below:

enter image description here

Note that adding a background color is not preferred as I would like to maintain the navigationBar tint effect when the list view is scrolled.

CodePudding user response:

It is inside NavigationView, so it should be also expanded, so child would have possibility to go outside safe area.

Here is fixed code (tested with Xcode 13.2 / iOS 15.2)

demo

var body: some View {
    NavigationView {
        TabView(selection: $selectedPage) {
            FirstList()
                .ignoresSafeArea()
                .tag(0)

            SecondList()
                .tag(1)
        }
        .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
        //.border(Color.red)    // for testing
        .ignoresSafeArea()                        // << here !!
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .principal) {
                Picker("", selection: $selectedPage) {
                    ForEach(pages, id: \.self) {
                        Text(String($0))
                    }
                }
                .scaledToFit()
                .pickerStyle(.segmented)
            }
        }
    }
    .ignoresSafeArea()         // << and here !!
}

CodePudding user response:

It is because List has its own background. You can either set listStyle to .plain or manually set the color of List background e.g. onAppear.

struct ContentView: View {
    @State private var selectedPage = 0
    private var pages = [0, 1]
    
    var body: some View {
        NavigationView {
            TabView(selection: $selectedPage) {
                FirstList()
                    .ignoresSafeArea()
                    .tag(0)
                
                SecondList()
                    .tag(1)
            }
            .ignoresSafeArea()
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
            .navigationBarTitleDisplayMode(.inline)
            .onAppear {
                // UITableView.appearance().backgroundColor = UIColor(Color.clear) // solution2
                
            }
            .toolbar {
                ToolbarItem(placement: .principal) {
                    Picker("", selection: $selectedPage) {
                        ForEach(pages, id: \.self) {
                            Text(String($0))
                        }
                    }
                    .scaledToFit()
                    .pickerStyle(.segmented)
                }
            }
        }
    }
}

struct FirstList: View {
    var body: some View {
        List {
            Text("0")
        }
        .listStyle(.plain) //solution1
    }
}

struct SecondList: View {
    var body: some View {
        List {
            Text("1")
        }
        .listStyle(.plain) //solution1
    }
}
  •  Tags:  
  • Related