I came across a weird Issue in SwiftUI. I created a simple View that only holds a Button and a TabView that uses the PageViewStyle. It seems that the TabView does not update it's content correctly depending on the State of the Variable. It seems that the content gets updated somehow but the View wont be updated how I would expect
Here is the Code of my View:
struct ContentView: View {
@State var numberOfPages: Int = 0
@State var selectedIndex = 0
var body: some View {
VStack {
Text("Tap Me").onTapGesture(count: 1, perform: {
self.numberOfPages = [2,5,10,15].randomElement()!
self.selectedIndex = 0
})
TabView(selection: $selectedIndex){
ForEach(0..<numberOfPages, id: \.self) { index in
Text("\(index)").background(Color.red)
}
}
.frame(height: 300)
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
}.background(Color.blue)
}
}
This is how the result looks after tapping the label several Times. The Initial State is no 0 Pages. After you tap i would expect that the content of the TabView changes so all Pages will be scrollable and visible but just the page indicator updates it State for some reason.
In the recent WWDC 2020, Apple introduced an additional style for TabView called PageTabViewStyle. This is equivalent to Horizontal Paging Scroll which is commonly used for the onboarding screen. A TabViewStyle that implements a paged scrolling TabView.
Add .tabViewStyle (PageTabViewStyle ()) at the end of TabView. Your tab should be able to scroll horizontally now. A Horizontal Page Scrolling is not complete without the page indicator.
It allows us to add the tab view and control the currently selected tab programmatically. The hidden feature of the TabView is that we can use it to show the multiple tabs with page indicators, and those can be controlled by scrolling between them.
To create scrolling pages with the TabView in SwiftUI, we need to call the view modifier tabViewStyle and pass an instance of PageTabViewStyle style. If we want to hide the page indicator, we specify the indexDisplayMode parameter for the PageTabViewStyle instance and set it to .never.
TabView
expects to have container of pages, but you included only one HStack
(with own dynamic content), moreover chaining number of pages you have to reset tab view, so here is a fix.
Tested with Xcode 12 / iOS 14
struct ContentView: View {
@State var numberOfPages: Int = 0
var body: some View {
VStack {
Text("Tap Me").onTapGesture(count: 1, perform: {
self.numberOfPages = [2,5,10,15].randomElement()!
})
if self.numberOfPages != 0 {
TabView {
ForEach(0..<numberOfPages, id: \.self) { index in
Text("\(index)").frame(width: 300).background(Color.red)
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
.frame(height: 300)
.id(numberOfPages) // << here !!
}
}
}
}
backup
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With