SwiftUI:如何在ForEach循环中随机设置Rectangle的Frame高度
问题解答
你想要在ForEach循环中为Rectangle设置随机高度,用.frame(height:)完全可行,而且ForEach正是批量创建这类重复视图的合适选择,以下是具体实现方案和注意事项:
两种随机高度实现方式
1. 动态随机高度(随视图刷新变化)
如果希望矩形高度每次视图刷新时都重新随机,可以直接在height参数中生成随机值:
struct SoundwaveView: View { var body: some View { HStack(spacing: 16) { ForEach(1..<20) { index in Rectangle() .frame(width: 6, height: CGFloat.random(in: 10...100)) // 10-100范围内的随机高度 .foregroundColor(.green) // 注意:原代码的.background会导致颜色超出矩形,用foregroundColor才是填充矩形本身 .cornerRadius(3) } } } }
注意:这种方式下,只要视图触发刷新(比如父视图状态变化),所有矩形高度都会重新生成,会有动态闪烁的效果。
2. 固定随机高度(初始化后不再变化)
如果希望每次视图加载时生成一组固定的随机高度,后续不再改变,可以提前生成随机值数组:
struct SoundwaveView: View { // 提前生成19个对应1..<20的随机高度,范围10-100 private let randomHeights: [CGFloat] = (1..<20).map { _ in CGFloat.random(in: 10...100) } var body: some View { HStack(spacing: 16) { ForEach(0..<randomHeights.count, id: \.self) { index in Rectangle() .frame(width: 6, height: randomHeights[index]) .foregroundColor(.green) .cornerRadius(3) } } } }
这种方式生成的高度只会在视图初始化时计算一次,后续保持稳定。
是否适合用ForEach?
完全适合。ForEach的核心作用就是基于数据源批量创建结构相似的视图,你的场景(19个仅高度不同的矩形)正好匹配它的使用场景,比手动写19个Rectangle代码高效且易维护。
优化:贴近真实声波效果
如果想要更接近你期望的「中间高、两侧低」的声波形态,可以不用纯均匀随机,改用正态分布随机数让高度集中在中间区间:
import GameKit // 需要导入GameKit框架 struct SoundwaveView: View { private let randomHeights: [CGFloat] = (1..<20).map { index in // 以60为均值、20为标准差生成随机数,再限制在10-100范围内 let gaussianValue = GKRandomDistribution(lowestValue: 10, highestValue: 100).nextGaussian() * 20 + 60 return CGFloat(max(10, min(100, gaussianValue))) } var body: some View { HStack(spacing: 16) { ForEach(0..<randomHeights.count, id: \.self) { index in Rectangle() .frame(width: 6, height: randomHeights[index]) .foregroundColor(.green) .cornerRadius(3) } } } }
内容的提问来源于stack exchange,提问作者Steven Schafer
相关产品推荐
相关产品推荐

