Tieme
Tieme

Reputation: 65429

edgesIgnoringSafeArea on TabView with PageTabViewStyle not working

Using a TabView as a pageviewer by using .tabViewStyle(PageTabViewStyle()) works fine, but trying to let it run from edge to edge by applying edgesIgnoringSafeArea does not seem to work.

What am I missing here?

struct ContentView: View {
    let colors: [Color] = [.red, .green, .blue]
    var body: some View {
        TabView {
            ForEach(0...2, id: \.self) { index in
                Rectangle()
                    .fill(colors[index])
            }
        }
        .tabViewStyle(PageTabViewStyle())
        .edgesIgnoringSafeArea(.all)
    }
}

TabView + PageTabViewStyle + edgesIgnoringSafeArea

Adding another .edgesIgnoringSafeArea(.all) to the Rectangle or ForEach also doen't work.

Note that all these questions are different because they do not use use PageTabViewStyle():

Their solution (adding edgesIgnoringSafeArea(.all)) doesn't work in this case.

Upvotes: 36

Views: 12570

Answers (7)

tim
tim

Reputation: 127

Wrapping TabView in a ScrollView as suggested by @kimigori here works but causes the page dots to become scrollable. To fix them in place use a horizontal ScrollView.

This is a re-usable PageView that works with ignoresSafeArea(_:edges:):

struct PageView<Content: View>: View {
    let content: () -> Content

    var body: some View {
        GeometryReader { geo in
            ScrollView(.horizontal) {
                TabView {
                    content()
                }
                .frame(width: geo.size.width, height: geo.size.height)
                .tabViewStyle(PageTabViewStyle())
            }
        }
    }

    init(@ViewBuilder content: @escaping () -> Content) {
        self.content = content
    }
}

Example:

TestPageView gif

struct TestPageView: View {
    var body: some View {
        PageView {
            ForEach(0...2, id: \.self) { index in
                ZStack {
                    Rectangle()
                        .fill([.red, .green, .blue][index])
                    Text("Page \(index + 1)")
                }
            }
        }
        .ignoresSafeArea()
    }
}

Upvotes: 7

Rob Phillips
Rob Phillips

Reputation: 375

Found this by accident, so hope it works for others. Works for me on iOS15 and 16, YMMV.

Add a background color to the TabView:

TabView(selection: $index) {
    YourTabViewContent
    .ignoresSafeArea()
}
.background(Color.background)
.tabViewStyle(.page(indexDisplayMode: .never))
.edgesIgnoringSafeArea(.all)

Upvotes: 7

Sergey Udalov
Sergey Udalov

Reputation: 91

Just use:

.ignoresSafeArea(edges:[.top,.bottom])

I suppose that TabView can't ignore leading and trailing, which is included in .all. However, if you manually set .top and .bottom it works fine.

Upvotes: 1

sjk.27
sjk.27

Reputation: 133

Update in SwiftUI 3.0:

 TabView {
            ForEach(0...2, id: \.self) { index in
                Rectangle()
                    .fill(colors[index])
            }
            .ignoresSafeArea()
        }
        .tabViewStyle(PageTabViewStyle())
        .edgesIgnoringSafeArea(.all)

Upvotes: 10

markiv
markiv

Reputation: 1684

I worked around this annoying issue by "extending" the TabView's height and "shifting" it towards the top by the same amount:

struct ContentView: View {
    var body: some View {
        let yExtension: CGFloat = 50
        GeometryReader { g in
            TabView {
                Color.red.overlay(Text("1"))
                Color.green.overlay(Text("2"))
                Color.blue.overlay(Text("3"))
                Color.orange.overlay(Text("4"))
            }
            .frame(width: g.size.width, height: g.size.height + yExtension)
            .tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
            .font(Font.title.bold())
        }
        .offset(y: -yExtension)
        .edgesIgnoringSafeArea(.all)
    }
}

Tested on Xcode 12.4, iOS 14.4:

demo animation

Upvotes: 3

kimigori
kimigori

Reputation: 977

  1. Remove .edgesIgnoringSafeArea(.all) from the TabView
  2. Add frame to the TabView with screen width and height
  3. Wrap a TabView with ScrollView
  4. Add .edgesIgnoringSafeArea(.all) to the ScrollView
struct ContentView: View {
    let colors: [Color] = [.red, .green, .blue]

    var body: some View {
        ScrollView {
            TabView {
                ForEach(0...2, id: \.self) { index in
                    Rectangle()
                        .fill(colors[index])
                }
            }
            .frame(
                width: UIScreen.main.bounds.width ,
                height: UIScreen.main.bounds.height
            )
            .tabViewStyle(PageTabViewStyle())
            
        }
        .edgesIgnoringSafeArea(.all)
    }
}

Upvotes: 40

Asperi
Asperi

Reputation: 258117

Here is a maximum what I've got... anyway I assume that originally it is a bug and worth submitting feedback to Apple.

Tested with Xcode 12b

demo

struct TestPagingStyle: View {
    let colors: [Color] = [.red, .green, .blue]
    var body: some View {
        ZStack {
            Color.black.overlay(
                GeometryReader { gp in
                    TabView {
                        ForEach(0..<3, id: \.self) { index in
                            Text("Hello, World \(index)")
                                .frame(width: gp.size.width, height: gp.size.height)
                                .background(colors[index])
                        }
                    }
                    .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
                }
            )
        }.edgesIgnoringSafeArea(.all)
    }
}

Upvotes: 6

Related Questions