I have a scrollable tabview that displays on the click of either button in the home view (ContentView). I want the 1st tab to show when "View 1" is clicked, and the 2nd tab to show when "View 2" is clicked. Once the tabview is opened, it should still function properly, meaning the tab buttons and scrolling still works correctly. Now that I think about it, this is similar to clicking on the "Followers" or "Following" button on Instagram.
When I click on "View 2" it shows the 2nd tab correctly, but when I click on the tab button for View 1, the screen does not show the View 1 text. Video. Does anyone know how to fix this bug? Thanks!
ContentView.swift:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationStack {
HStack {
NavigationLink {
ScrollTab(currentTab: 0)
} label: {
Text("View 1")
.font(.subheadline)
.fontWeight(.semibold)
}
NavigationLink {
ScrollTab(currentTab: 1)
} label: {
VStack {
Text("View 2")
.font(.subheadline)
.fontWeight(.semibold)
}
.frame(width: 76)
}
}
}
}
}
ScrollTab.swift:
struct ScrollTab: View {
@State private var currentTab: Int = 0
init(currentTab: Int) {
_currentTab = State(initialValue: currentTab)
}
var body: some View {
Spacer()
VStack(alignment: .center, spacing: 0) {
TabBarView(currentTab: self.$currentTab)
TabView(selection: self.$currentTab) {
Text("This is view 1").tag(0)
.onAppear() {
self.currentTab = 0
}
Text("This is view 2").tag(1)
.onAppear() {
self.currentTab = 1
}
}
.tabViewStyle(.page(indexDisplayMode: .never))
.background(Color.secondary)
}
.edgesIgnoringSafeArea(.all)
}
}
struct TabBarView: View {
@Binding var currentTab: Int
@Namespace var namespace
var tabBarOptions: [String] = ["View 1", "View 2"]
var body: some View {
HStack(spacing: 20) {
ForEach(Array(zip(self.tabBarOptions.indices,
self.tabBarOptions)),
id: \.0,
content: {
index, name in
TabBarItem(currentTab: self.$currentTab,
namespace: namespace.self,
tabBarItemName: name,
tab: index)
})
}
.padding(.horizontal)
.background(Color.orange) // <<<< Remove
.frame(height: 80)
}
}
struct TabBarItem: View {
@Binding var currentTab: Int
let namespace: Namespace.ID
var tabBarItemName: String
var tab: Int
var body: some View {
Button {
self.currentTab = tab
} label: {
VStack {
Spacer()
Text(tabBarItemName)
if currentTab == tab {
Color.black
.frame(height: 2)
.matchedGeometryEffect(id: "underline",
in: namespace,
properties: .frame)
} else {
Color.clear.frame(height: 2)
}
}
.animation(.spring(), value: self.currentTab)
}
.buttonStyle(.plain)
}
}
As I stated with the comment above, under the line of TabView(selection: self.$currentTab), you have two Text views with onAppear. That's where a problem occurs.
So I have separated those two views from the ScrollTab view and created another named TextView as follows.
import SwiftUI
struct ScrollTab: View {
@State private var currentTab: Int = 0
init(currentTab: Int) {
_currentTab = State(initialValue: currentTab)
}
var body: some View {
Spacer()
VStack(alignment: .center, spacing: 0) {
TabBarView(currentTab: self.$currentTab)
TabView(selection: self.$currentTab) {
TextView(currentTab: $currentTab)
}
.tabViewStyle(.page(indexDisplayMode: .never))
.background(Color.secondary)
}
.edgesIgnoringSafeArea(.all)
}
}
#Preview {
ScrollTab(currentTab: 1)
}
struct TextView: View {
@Binding var currentTab: Int
var body: some View {
VStack {
if currentTab == 0 {
Text("This is view 1")
} else {
Text("This is view 2")
}
}
}
}
I haven't touched ContentView and other actors.
UPDATE
I have gotten rid of TextView. You can now scroll it horizontally to switch tabs.
struct ScrollTab: View {
@State private var currentTab: Int = 0
init(currentTab: Int) {
_currentTab = State(initialValue: currentTab)
}
var body: some View {
Spacer()
VStack(alignment: .center, spacing: 0) {
TabBarView(currentTab: self.$currentTab)
TabView(selection: self.$currentTab) {
ForEach(0...1, id: \.self) { number in
VStack {
if number == 0 {
Text("This is view 1")
} else {
Text("This is view 2")
}
}.tag(number)
}
}
.tabViewStyle(.page(indexDisplayMode: .never))
.background(Color.secondary)
}
.edgesIgnoringSafeArea(.all)
}
}
UPDATE 2
struct ScrollTab: View {
@State private var currentTab: Int = 0
init(currentTab: Int) {
_currentTab = State(initialValue: currentTab)
}
var body: some View {
Spacer()
VStack(alignment: .center, spacing: 0) {
TabBarView(currentTab: self.$currentTab)
TabView(selection: self.$currentTab) {
VStack {
if currentTab == 0 {
Text("This is view 1").tag(0)
} else {
Text("This is view 2").tag(1)
}
}
}
.tabViewStyle(.page(indexDisplayMode: .never))
.background(Color.secondary)
}
.edgesIgnoringSafeArea(.all)
}
}