I've been experimenting with TabView
and tabViewStyle
and I've run into a problem with my code I can't figure out.
In the code below, when the app opens up on my device I start on the HomeScreen()
(as expected) but if I tap on Profile
in the top bar, the tab navigation doesn't happen. The Profile
text turns red (indicating that pageIndex
has been updated), but for reasons I can't figure out, the TabView
isn't updating accordingly.
BUT, if I open the app and tap on Settings
in the top bar, the tab navigation happens as expected.
Swiping works as expected, no issues there.
Have I missed something obvious?
Steps to reproduce:
- Copy code into xcode
- Run on simulator / canvas / device
- Tap
Profile
(don't swipe or tap anything else) Profile
will turn red, but the page won't be animated left to theProfile
screen.- If you tap
Settings
or swipe any direction, tappingProfile
will work as expected.
import SwiftUI
struct SwipeNavigation2: View {
@State var pageIndex = 1
var body: some View {
NavigationView {
TabView(selection: self.$pageIndex) {
// The screen to the "left" of the Home screen
ProfileScreen()
.tag(0)
// The screen we want the app to load on
HomeScreen()
.tag(1)
// The screen to the "right" of the Home screen
SettingsScreen()
.tag(2)
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button {
withAnimation(.spring()) {
pageIndex = 0
}
} label: {
Text("Profile")
.foregroundColor(pageIndex == 0 ? .red : .primary)
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button {
withAnimation(.spring()) {
pageIndex = 2
}
} label: {
Text("Settings")
.foregroundColor(pageIndex == 2 ? .red : .primary)
}
}
}
}
}
}
private struct ProfileScreen: View {
var body: some View {
Text("Profile screen")
}
}
private struct HomeScreen: View {
var body: some View {
Text("Home screen")
}
}
private struct SettingsScreen: View {
var body: some View {
Text("Settings screen")
}
}
Edit:
I've taken some of the suggestions and amended the code as such:
struct SwipeNavigation2: View {
@State var pageIndex = 0
var body: some View {
NavigationView {
TabView(selection: self.$pageIndex) {
ProfileScreen()
.tag(0)
HomeScreen()
.tag(1)
SettingsScreen()
.tag(2)
}
.onAppear {
pageIndex = 1
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button {
withAnimation(.spring()) {
pageIndex = 0
}
} label: {
Text("Profile")
.foregroundColor(pageIndex == 0 ? .red : .primary)
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button {
withAnimation(.spring()) {
pageIndex = 2
}
} label: {
Text("Settings")
.foregroundColor(pageIndex == 2 ? .red : .primary)
}
}
}
}
}
}
Edit 1:
Here's a recording from my simulator (Xcode14.1), on an iPhone 14. You'll see once the recording starts, I tap on Profile
(which turns it red), but the TabView
isn't moving me to the correct page.
https://i.stack.imgur.com/2uJ0c.jpg
Edit 2:
It gets weirder. I've tested the following devices in XCode simulator:
- iPhone 13 (doesn't work)
- iPhone 13 Mini (doesn't work)
- iPhone 14 (doesn't work)
- iPhone 14 Pro (works)
- iPhone 14 Pro Max (works)