You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中LazyGrid点击切换单个Item背景颜色问题

解决SwiftUI LazyGrid点击项切换背景不更新的问题

问题根源

  1. 数据模型无响应式能力:Day是普通类,属性isSelected变化时无法通知视图刷新。
  2. 视图未监听状态变化:days是普通变量,SwiftUI不会追踪其内部元素的状态变更。
  3. 点击逻辑错误:固定修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:54:56