SwiftUI中LazyGrid点击切换单个Item背景颜色问题
解决SwiftUI LazyGrid点击项切换背景不更新的问题
问题根源
- 数据模型无响应式能力:
Day是普通类,属性isSelected变化时无法通知视图刷新。 - 视图未监听状态变化:
days是普通变量,SwiftUI不会追踪其内部元素的状态变更。 - 点击逻辑错误:固定修改
days[0]的状态,而非当前点击的网格项。
修复步骤
1. 改造数据模型为响应式类型
让Day遵循ObservableObject协议,并用@Published标记需要监听变化的属性,确保属性变更时能触发视图更新:
class Day: Identifiable, ObservableObject { let id = UUID() let value: Int @Published var isSelected: Bool init(value: Int, isSelected: Bool) { self.value = value self.isSelected = isSelected } }
2. 让视图监听数据状态
将ContentView中的days变量用@State修饰,让SwiftUI追踪数组及其内部元素的变化:
@State var days = [ Day(value: 1, isSelected: true), Day(value: 2, isSelected: false), Day(value: 3, isSelected: false), Day(value: 4, isSelected: true) ]
3. 修正点击逻辑,切换当前项状态
在ForEach中使用绑定获取当前Day对象,点击时切换其isSelected状态:
var body: some View { ScrollView { LazyVGrid(columns: layout) { ForEach($days) { $day in Capsule() .overlay(Text("\(day.value)").foregroundColor(.white)) .foregroundColor(day.isSelected ? .blue : .red) .frame(height: 40) .onTapGesture { day.isSelected.toggle() } } } } }
完整修复后的代码
import SwiftUI class Day: Identifiable, ObservableObject { let id = UUID() let value: Int @Published var isSelected: Bool init(value: Int, isSelected: Bool) { self.value = value self.isSelected = isSelected } } struct ContentView: View { @State var days = [ Day(value: 1, isSelected: true), Day(value: 2, isSelected: false), Day(value: 3, isSelected: false), Day(value: 4, isSelected: true) ] let layout = [ GridItem(.fixed(40)), GridItem(.fixed(40)), GridItem(.fixed(40)), GridItem(.fixed(40)) ] var body: some View { ScrollView { LazyVGrid(columns: layout) { ForEach($days) { $day in Capsule() .overlay(Text("\(day.value)").foregroundColor(.white)) .foregroundColor(day.isSelected ? .blue : .red) .frame(height: 40) .onTapGesture { day.isSelected.toggle() } } } } } }
内容的提问来源于stack exchange,提问作者Mohmed Showekh
相关产品推荐
相关产品推荐

