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. If anyone has any idea on how to solve this, please let me know. 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 var currentTab: Int = 0
init(currentTab: Int) {
self.currentTab = 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)
}
}
Edit: Thanks to vadian's reply, I was able to get it fixed. However, I am running into an issue where the tabview is not working correctly when I click the tab buttons (link below). Any suggestions here?
This is a common mistake. You cannot initialize
@Stateproperty wrappers just by assigning the value.Replace the first lines of
ScrollTabwithAnd – although not related to the issue – it's highly recommended to declare
@Stateproperty wrappers always asprivate.