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
相关产品推荐
相关产品推荐

