I want to change items in LazyVGrid on tap. I've implemented color and zIndex to be depended on selectedItemIndex, which is changed when item is tapped.
import SwiftUI
struct FilmRoll: View {
@State private var selectedItemIndex: Double = 5
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
ScrollView {
LazyVGrid(columns: [GridItem(), GridItem(), GridItem()]) {
ForEach(1..<13) { index in
Rectangle()
.fill(Color(
red: (selectedItemIndex == Double(index)) ? 1 : Double(index)/24.0 + 0.5,
green: 0,
blue: 0))
.zIndex((selectedItemIndex == Double(index)) ? 1 : 0)
.frame(width: 180, height: 180)
.border(Color.black)
.rotationEffect(.degrees(45))
.onTapGesture {
selectedItemIndex = Double(index)
print("selected item \(selectedItemIndex)")
}
}
}
}
}
}
}
Result is that color is updated when @State selectedItemIndex changes, but zIndex stays the same as it was on start. What am I missing?
To achieve what you want, you could try this approach adding
an id
to the ForEach
to force it to refresh.
Note, it is better to have Int
types for comparisons, as shown in the code:
struct ContentView: View {
var body: some View {
FilmRoll()
}
}
struct FilmRoll: View {
@State private var selectedItemIndex: Int = 5 // <-- here
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
ScrollView {
LazyVGrid(columns: [GridItem(), GridItem(), GridItem()]) {
ForEach(1..<13) { index in
Rectangle()
.fill(Color(
red: (selectedItemIndex == index) ? 1 : Double(index)/24.0 + 0.5,
green: 0,
blue: 0))
.zIndex(selectedItemIndex == index ? 1 : 0)
.frame(width: 180, height: 180)
.border(.black)
.rotationEffect(.degrees(45))
.onTapGesture {
selectedItemIndex = index
print("----> selected item \(selectedItemIndex)")
}
}
.id(selectedItemIndex) // <-- here
}
}
}
}
}