In my app I have TabView PageTabViewStyle(indexDisplayMode: .never)
style and I want to display banner view on the top of the screen which, when displayed, pushes all other content down. Basic view setup is:
struct ContentView: View {
@StateObject private var viewModel = ContentViewModel()
@State var selectedTab = 0
var body: some View {
return VStack(spacing: 0) {
if viewModel.showingBanner {
bannerView
}
TabView(selection: $selectedTab, content: {
ForEach(0..<3) { index in
tabContents(index)
.tag(index)
}
})
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
}
.ignoresSafeArea(edges: [.bottom])
}
func tabContents(_ index: Int) -> some View {
VStack {
Text("Hello, \(index)!")
.font(.system(size: 48, weight: .bold))
}
}
var bannerView: some View {
VStack {
Label("Banner", systemImage: "exclamationmark.triangle")
.font(.largeTitle)
.foregroundStyle(.white)
.padding(4)
}
.frame(maxWidth: .infinity)
.background(.red)
.onTapGesture {
withAnimation {
viewModel.showingBanner = false
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation {
viewModel.showingBanner = true
}
}
}
}
}
The problem is that when banner view is added, tab view content jitters during animation. There's several workarounds that make jittering go away, but by using them I lose some functionality:
- remove
.ignoresSafeArea(edges: [.bottom])
- I need content to extend into safe area - don't use
page
tabViewStyle - I lose scrolling between tabs - Use plain ScrollView - I lose automatic binding to the selected tab
Am I missing something in my TabView or content setup that causes this issue or my only recourse is to switch to using ScrollView instead of TabView for my use case?