'SwiftUI select multiple item in a lazyhgrid

With SwiftUI this is my current code:

import SwiftUI

enum Items: String, CaseIterable, Equatable {
    case item1
    case item2
    case item3
    case item4
    case item5
    case item6
}

struct GridPicker: View {
    var rows: [GridItem] = Array(repeating: .init(.flexible()), count: 3)
   


@State var isPressed = false

var body: some View {
    NavigationView {
        ScrollView(.horizontal) {
            LazyHGrid(rows: rows) {
                ForEach(Items.allCases, id: \.self) { value in
                    Button(action: {
                        isPressed = true
                    }, label: {
                        Text(value.rawValue)
                            .tag(value)
                            .foregroundColor(isPressed ? .purple : .white)
                    })
                    
                    .frame(width: 85, height: 85)
                    .background(isPressed ? Color.white : Color.purple)
                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                }
            }
        }
    }
    .navigationViewStyle(StackNavigationViewStyle())
    
}
}

struct GridPicker_Previews: PreviewProvider {
    static var previews: some View {
        GridPicker()
    }
}

I am trying to make it so I get a result like in the picture below.

Right now I have an enum what cases. I am trying to make each case selectable and then get back what cases in the enum the user has pressed so I can save the results in Core Data. Please note that the attribute in core data that I am trying to save this to is an Array of Strings.

The current issue:

When I press on one of the list items all of the items change color (I only want the selected item to change color)

How do I get back what case in the enum the user pressed in an array of strings format?

Thanks in advance. enter image description here



Solution 1:[1]

Add a new @State array to hold the selected items.

enum Items: String, CaseIterable, Equatable {
    case item1
    case item2
    case item3
    case item4
    case item5
    case item6
}

struct GridPicker: View {
    var rows: [GridItem] = Array(repeating: .init(.flexible()), count: 3)
    
    @State  var selectedItems: [Items] = []
    
    
    var body: some View {
        NavigationView {
            ScrollView(.horizontal) {
                LazyHGrid(rows: rows) {
                    ForEach(Items.allCases, id: \.self) { item in
                        GridColumn(item: item, items: $selectedItems)
                    }
                }
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
        
    }
}

struct GridPicker_Previews: PreviewProvider {
    static var previews: some View {
        GridPicker()
    }
}


struct GridColumn:View {
    let item: Items
    
    @Binding var items: [Items]
    
    var body: some View {
        Button(action: {
            if items.contains(item) {
                items.removeAll { $0 == item}
            } else {
                items.append(item)
            }
        }, label: {
            Text(item.rawValue)
                .tag(item)
                .foregroundColor(items.contains(item) ? .purple : .white)
        })
        
        .frame(width: 85, height: 85)
        .background(items.contains(item) ? Color.white : Color.purple)
        .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
    }
}

This is not an array of strings but an array of Items (enum). Use an array of String should you need string.

You do not need to use isPressed.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1