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

SwiftUI视图重绘问题:如何避免矩形随计时器触发重复变色

解决SwiftUI矩形随机颜色随视图重绘刷新的问题

当前代码中,每次计时器触发更新circleX时,整个ContentView的body会重新计算,而Rectangle的.fill(Color.random)会在每次重绘时重新生成随机颜色,导致矩形颜色不断变化。核心原因是随机颜色没有被持久化存储,而是在视图渲染时动态生成。

解决方案:
我们需要提前生成并存储所有矩形的初始随机颜色,确保颜色只在视图初始化时生成一次,后续重绘时直接使用预存的颜色值。

修改后的完整代码:

struct ContentView: View {
    let width: CGFloat = 400
    let height: CGFloat = 400
    let spacing: CGFloat = 8.0
    let numRows = 20
    var tileSize: CGFloat {
        height / 5
    }
    
    let timer = Timer.publish(every: 3.0, on: .main, in: .common).autoconnect()
    @State private var circleX: CGFloat = 0.0
    // 存储所有矩形的初始随机颜色
    @State private var tileColors: [[Color]] = []
    
    init() {
        let numColumns = Int(tileSize)
        // 初始化时生成所有行和列的随机颜色
        tileColors = Array(repeating: Array(repeating: Color.random, count: numColumns), count: numRows)
    }
    
    var body: some View {
        let numColumns = Int(tileSize)
        
        ZStack {
            Grid(horizontalSpacing: spacing, verticalSpacing: spacing) {
                ForEach(0..<numRows, id: \.self) { rowIndex in
                    GridRow {
                        ForEach(0..<numColumns, id: \.self) { colIndex in
                            Rectangle()
                                // 使用预存的颜色,不再动态生成
                                .fill(tileColors[rowIndex][colIndex])
                                .frame(width: tileSize, height: tileSize)
                        }
                    }
                }
            }
            
            Circle()
                .fill(.red)
                .frame(width:50, height: 50)
                .offset(x: circleX, y: 0)
        }
        .onReceive(timer) { time in
            circleX += 10
        }
    }
}

#Preview {
    ContentView()
}

extension Color {
    static var random: Color {
        Color(red: .random(in: 0...1),
              green: .random(in: 0...1),
              blue: .random(in: 0...1))
    }
}

关键修改点说明:

  • 添加@State private var tileColors: [[Color]]用于存储二维颜色数组,对应网格的行和列
  • 在init()方法中一次性生成所有矩形的随机颜色,确保颜色只初始化一次
  • 将Rectangle的.fill(Color.random)替换为.fill(tileColors[rowIndex][colIndex]),直接使用预存颜色

这样修改后,即使计时器触发circleX更新导致视图重绘,矩形的颜色也会保持初始生成的随机值,不会随重绘变化。

内容的提问来源于stack exchange,提问作者soleil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:15:13