Reputation: 377
I have some fullscreen views that I want to be able to swipe between in a TabView, and I know that I can expand the whole TabView container outside the Safe Area using .ignoresSafeArea()
however the TabView page index also gets lowered, and I wish that to maintain its constraints inside the Safe Area.
Tab Page Index higher within safe area, but background not filling screen
Tab Page Index lower outside safe area, but background filling screen.
I need the Tab Page Index to be higher within the safe area, but the background (TabView View) to fill the screen.
Upvotes: 2
Views: 807
Reputation: 21720
Just getting the background of the TabView
to ignore the safe area insets is easy:
TabView
using .background()
, which ignores the safe area edges by default - see background(_:ignoresSafeAreaEdges:):TabView {
// ...
}
.tabViewStyle(.page)
.background(.blue)
.ignoresSafeArea()
to the background content:TabView {
// ...
}
.tabViewStyle(.page)
.background {
MyBackground().ignoresSafeArea()
}
However, you said that your views are full-screen, so I expect you want the TabView
to respect the safe area insets (to keep the dots in the higher position) but have the views ignore the insets. I couldn't find a way to get this to work.
As a workaround, you can emulate the functionality of a TabView
by using a ScrollView
.
.scrollTargetBehavior(.paging)
to allow the views to be switched by swiping, very similar to a TabView
..scrollTargetLayout()
in combination with .scrollPosition
to track the selected view.The example below has page dots that resemble the page indicators of a TabView
:
struct ContentView: View {
private let colors: [Color] = [.yellow, .orange, .green]
@State private var selectedIndex: Int? = 0
var body: some View {
ScrollView(.horizontal) {
HStack(spacing: 0) {
ForEach(Array(colors.enumerated()), id: \.offset) { offset, color in
color
.containerRelativeFrame(.horizontal)
}
}
.scrollTargetLayout()
}
.ignoresSafeArea()
.scrollIndicators(.hidden)
.scrollTargetBehavior(.paging)
.scrollPosition(id: $selectedIndex)
.overlay(alignment: .bottom) {
PageDots(nPages: colors.count, currentIndex: selectedIndex ?? 0)
}
}
}
struct PageDots: View {
let nPages: Int
let currentIndex: Int
var body: some View {
HStack(spacing: 10) {
ForEach(0..<nPages, id: \.self) { index in
Circle()
.fill(.white)
.opacity(index == currentIndex ? 1.0 : 0.45)
.frame(width: 8)
}
}
.animation(.easeInOut(duration: 0.2), value: currentIndex)
.padding(.bottom, 20)
}
}
Upvotes: 3