Home > OS >  Issues with coloring the tapped on symbol image in a ForEach
Issues with coloring the tapped on symbol image in a ForEach

Time:06-27

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)
                    })
            }
        }
    }
}
  • Related