ViOS
ViOS

Reputation: 233

ForEach view can't apply the view modifier to selected view

I have a simple horizontal list view that displays the list of colours and the problem is that I don't know how to apply border to only one selected view, for now it's adding the white border to all views in the list on didTap, please help if you know how to achieve it, thanks 🙌

Here's the code:

struct Colour: Identifiable {
    var id: Int
    var color: Color
}

struct ContentView: View {
    @State private var didTap = false
    @State private var colors: [Colour] = [
        Colour(id: 1, color: .black),
        Colour(id: 2, color: .yellow),
        Colour(id: 3, color: .orange),
        Colour(id: 4, color: .green),
        Colour(id: 5, color: .red),
        Colour(id: 6, color: .blue),
        Colour(id: 7, color: .pink),
        Colour(id: 8, color: .purple),
    ]
    
    var body: some View {
        ZStack {
            Color.gray.opacity(0.2)
                .ignoresSafeArea()
            
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 4) {
                    ForEach(colors) { color in
                        Rectangle()
                            .fill(color.color)
                            .frame(width: 100, height: 150)
                            .overlay(
                                Rectangle()
                                    .stroke(didTap ? Color.white : .clear, lineWidth: 5)
                                    .animation(.spring())
                            )
                            .padding(5)
                            .onTapGesture {
                                didTap.toggle()
                                print(color.id)
                            }
                    }
                }
                .padding(.leading, 8)
            }
        }
    }
}

Upvotes: 1

Views: 396

Answers (1)

Asperi
Asperi

Reputation: 257701

You need to store id of selected color instead of bool.

Here is simple demo (deselect on tap on same element is your excise). Tested with Xcode 12.5 / iOS 14.5

demo

struct ContentView: View {
    @State private var selected = -1          // << here !!
    @State private var colors: [Colour] = [
        Colour(id: 1, color: .black),
        Colour(id: 2, color: .yellow),
        Colour(id: 3, color: .orange),
        Colour(id: 4, color: .green),
        Colour(id: 5, color: .red),
        Colour(id: 6, color: .blue),
        Colour(id: 7, color: .pink),
        Colour(id: 8, color: .purple),
    ]

    var body: some View {
        ZStack {
            Color.gray.opacity(0.2)
                .ignoresSafeArea()

            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 4) {
                    ForEach(colors) { color in
                        Rectangle()
                            .fill(color.color)
                            .frame(width: 100, height: 150)
                            .overlay(
                                Rectangle()
                                    .stroke(selected == color.id ? Color.white : .clear, lineWidth: 5)
                                    .animation(.spring())
                            )
                            .padding(5)
                            .onTapGesture {
                                selected = color.id    // << here !!
                                print(color.id)
                            }
                    }
                }
                .padding(.leading, 8)
            }
        }
    }
}

Upvotes: 1

Related Questions