SwiftUI select multiple item in a lazyhgrid

Viewed 1609

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

1 Answers

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.

Related