I'm having a bit of a challenge figuring this one out. In the below code I create a TabView and have the ability to switch which tab is active using the .tag(), but I have a horizontal ScrollView of Tab items. Each tab screen displays similar information so I am using a single view to create it and then a ForEach loop to go through the items. But it breaks the .tag() function and I can't seem to figure out how to get it to work using the ForEach loop. Any ideas on how to approach this or what I am missing?
import SwiftUI
\\ Working code with normal Swipable tabs using .tag()
struct ContentView: View {
var body: some View {
CustomTabView()
}
}
struct CustomTabView: View {
@State var selectedTab = "house"
var body: some View {
ZStack(alignment: Alignment(horizontal: .center, vertical: .bottom)) {
TabView(selection: $selectedTab) {
HouseView()
.tag("house")
EnvelopeView()
.tag("envelope")
FolderView()
.tag("folder")
SettingsView()
.tag("gear")
SliderView()
.tag("slider.horizontal.3")
VideoView()
.tag("video")
UpView()
.tag("arrow.up.doc")
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.ignoresSafeArea(.all, edges: .bottom)
ScrollView(.horizontal, showsIndicators: false, content: {
HStack {
ForEach(tabs,id: \.self){image in
TabButton(image: image, selectedTab: $selectedTab)
}
}
})
.padding(.horizontal, 25)
.padding(.vertical, 5)
.background(Color.white)
.clipShape(Capsule())
.shadow(color: Color.black.opacity(0.15), radius: 5, x: 5, y: 5)
.shadow(color: Color.black.opacity(0.15), radius: 5, x: -5, y: -5)
.padding(.horizontal)
}
.ignoresSafeArea(.keyboard, edges: .bottom)
.background(Color.black.opacity(0.05).ignoresSafeArea(.all, edges: .all))
}
}
// tab...
var tabs = ["house", "envelope", "folder", "gear", "slider.horizontal.3", "video", "arrow.up.doc"]
struct TabButton: View {
var image : String
@Binding var selectedTab : String
var body: some View {
Button(action: {selectedTab = image}) {
Image(systemName: image)
.renderingMode(.template)
.opacity(self.selectedTab == image ? (1) : (0.5))
.padding()
}
}
}
struct HouseView: View {
var body: some View {
VStack {
Text("House View")
}
}
}
struct EnvelopeView: View {
var body: some View {
VStack {
Text("Envelope View")
}
}
}
struct FolderView: View {
var body: some View {
VStack {
Text("Folder View")
}
}
}
struct SettingsView: View {
var body: some View {
VStack {
Text("Settings View")
}
}
}
struct SliderView: View {
var body: some View {
VStack {
Text("Slider View")
}
}
}
struct VideoView: View {
var body: some View {
VStack {
Text("Video View")
}
}
}
struct UpView: View {
var body: some View {
VStack {
Text("Up View")
}
}
}
Problematic Code after the ForEach loop on the views in the TabView. The views populate but it breaks the .tag() functionality and I'm lost as to how to make it work again.
import SwiftUI
struct ContentView: View {
var body: some View {
CustomTabView()
}
}
struct CustomTabView: View {
@State var selectedTab = "house"
@State var viewData : AllViewData!
var body: some View {
ZStack(alignment: Alignment(horizontal: .center, vertical: .bottom)) {
TabView(selection: $selectedTab) {
ForEach(allViews){views in
ViewsCardView(viewData: views)
.tag("//not sure if this is the right place for the .tag()")
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.ignoresSafeArea(.all, edges: .bottom)
ScrollView(.horizontal, showsIndicators: false, content: {
HStack {
ForEach(tabs,id: \.self){image in
TabButton(image: image, selectedTab: $selectedTab)
}
}
})
.padding(.horizontal, 25)
.padding(.vertical, 5)
.background(Color.white)
.clipShape(Capsule())
.shadow(color: Color.black.opacity(0.15), radius: 5, x: 5, y: 5)
.shadow(color: Color.black.opacity(0.15), radius: 5, x: -5, y: -5)
.padding(.horizontal)
}
.background(Color.black.opacity(0.05).ignoresSafeArea(.all, edges: .all))
}
}
// tab...
var tabs = ["house", "envelope", "folder", "gear", "slider.horizontal.3", "video", "arrow.up.doc"]
struct TabButton: View {
var image : String
@Binding var selectedTab : String
var body: some View {
Button(action: {selectedTab = image}) {
Image(systemName: image)
.renderingMode(.template)
.opacity(self.selectedTab == image ? (1) : (0.5))
.padding()
}
}
}
struct ViewsCardView: View {
@State var viewData : AllViewData!
var body: some View {
VStack {
Text(viewData.name)
}
}
}
struct AllViewData : Identifiable {
var id = UUID().uuidString
var name : String
}
var allViews = [
AllViewData(name: "House"),
AllViewData(name: "Envelope"),
AllViewData(name: "Folder"),
AllViewData(name: "Settings"),
AllViewData(name: "Slider"),
AllViewData(name: "Video"),
AllViewData(name: "Up"),
]