I have a view that displays several symbol images. When a symbol image is tapped on by the user I want the symbol image to turn blue. When the user taps on another symbol image I want the old symbol image to go back to its original color and the new symbol image to turn blue.
The current behavior, however, is that the previously tapped on symbol images remain blue. This is not the behavior I want. I only want the single, currently selected symbol image to be blue.
import SwiftUI
struct IconsView: View {
private let columns = [ GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()) ]
private let icons = [ "a.circle", "b.circle", "c.circle", "d.circle", "e.circle", "f.circle", "g.circle", "h.circle",
"i.circle" ]
var body: some View {
LazyVGrid(columns: columns) {
ForEach(icons, id: \.self) { item in
IconsSubView(strIcon: item)
}
}
}
}
import SwiftUI
struct IconsSubView: View {
let strIcon: String
@State private var isSelectedIcon = false
var body: some View {
Image(systemName: strIcon).tag(strIcon)
.foregroundColor(isSelectedIcon == true ? Color.blue : Color.primary)
.font(.system(size: 50))
.onTapGesture(perform: {
isSelectedIcon.toggle()
print(strIcon)
})
}
}
Previously I had the two views in one. The problem I was having back then was that when I tapped on one symbol image ALL of them would turn blue.
import SwiftUI
struct IconsViewOld: View {
@State private var isSelectedIcon = false
private let columns = [ GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()) ]
private let icons = [ "a.circle", "b.circle", "c.circle", "d.circle", "e.circle", "f.circle", "g.circle", "h.circle",
"i.circle" ]
var body: some View {
LazyVGrid(columns: columns) {
ForEach(icons, id: \.self) { item in
Image(systemName: item)
.foregroundColor(isSelectedIcon == true ? Color.blue : Color.primary)
.font(.system(size: 50))
.onTapGesture(perform: {
isSelectedIcon.toggle()
print(item)
})
}
}
}
}
I would appreciate any help.
Thank you.
I‘m using XCode 13.4.1 and iOS 15.5
CodePudding user response:
You can use previous variant, but instead of Bool, store tapped item, like
struct IconsViewOld: View {
@State private var selectedIcon = "" // << here !!
private let columns = [ GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()) ]
private let icons = [ "a.circle", "b.circle", "c.circle", "d.circle", "e.circle", "f.circle", "g.circle", "h.circle",
"i.circle" ]
var body: some View {
LazyVGrid(columns: columns) {
ForEach(icons, id: \.self) { item in
Image(systemName: item)
// modify color for matched item !!
.foregroundColor(selectedIcon == item ? Color.blue : Color.primary)
.font(.system(size: 50))
.onTapGesture(perform: {
selectedIcon = item // << here !!
print(item)
})
}
}
}
}