I activate a .contextMenu
by selecting a GridItem
in a LazyVGrid
. Then change a Bool
value in just that selected GridItem
to update its contents.
My issue is after tapping the Button in the .contextMenu
and changing the Bool. The changes are shown in all GridItem not just selected.
How. to just reflect changes in selected GridItem?
import SwiftUI
struct GridItemView: View {
var id : Int
@Binding var isRed : Bool
var body: some View {
VStack {
Text("Hello")
Image(systemName: "globe.europe.africa")
}
.foregroundStyle(isRed ? .red : .black)
.padding()
.border(.black)
}
}
import SwiftUI
struct ContentView: View {
let gridLayout = Array(repeating: GridItem(.flexible(), spacing: 0), count: 4)
let numberOfGridItems = 1092
@State private var isRed : Bool = false
var body: some View {
VStack {
ScrollView(.vertical) {
LazyVGrid(columns: gridLayout){
ForEach(0..<numberOfGridItems, id: \.self){ gridItemIndex in
let myGridItem = GridItemView(id: gridItemIndex, isRed: $isRed)
myGridItem.contextMenu{
Button(action: {
myGridItem.isRed.toggle()
},
label: {
Label("Toggle isRed for gridItemIndex \(myGridItem.id)", systemImage: "paintbrush.fill")
})
}
}
}.scrollTargetLayout()
}.scrollTargetBehavior(.viewAligned)
}
}
}
**Sorry 1st image should have shown all items as Red
I was able to find a solution from This Post
rather than having a @Binding
to a Bool which was setting the Bool value of all my GridItems not just those which were selected. I instead added the gridItemIndex
to an Array @State private var isSelected : [Int] = []
and moved the.contextMenu
(Though have changed to an overlay
) to perform the actions from being created inside the ForEach
where I create my LazyVGrid
to the GridItemView
itself and handle the changes there.
struct ContentView: View {
let gridLayout = Array(repeating: GridItem(.flexible(), spacing: 0), count: 3)
let numberOfGridItems = 9//1092
@State private var isSelected : [Int] = []
var body: some View {
VStack {
ScrollView(.vertical) {
LazyVGrid(columns: gridLayout){
ForEach(0..<numberOfGridItems, id: \.self){ gridItemIndex in
GridItemView(gridItemViewID: gridItemIndex, isSelectedGridItems: $isSelected)
}
}.scrollTargetLayout()
}.scrollTargetBehavior(.viewAligned)
}
}
}
struct GridItemView: View {
// renamed from var id : Int
let gridItemViewID : Int
@Binding var isSelectedGridItems : [Int]
var body: some View {
VStack {
Image(systemName: "globe.europe.africa")
}
.foregroundStyle(isSelectedGridItems.contains(gridItemViewID) ? .red : .black)
.padding()
.border(.black)
//changed from .contextMenu to .overlay
.overlay(alignment: .bottomTrailing) {
Menu {
Button("Change to Red", action: {
if isSelectedGridItems.contains(gridItemViewID) {
isSelectedGridItems.removeAll {
return $0 == gridItemViewID
}
}
else{
isSelectedGridItems.append(gridItemViewID)
}
})
} label: {
Image(systemName: "ellipsis.circle.fill")
.padding(2)
}.foregroundStyle(.black)
}
}
}