LazyVGrid中按钮间出现异常间隙,如何解决?
LazyVGrid间隙问题的原因及解决方法
问题根源
你的代码生成dates数组时会产生重复的Date值:
- 当计算出的时间为12:00/12:15/12:30/12:45时,代码会给这些时间加1小时,转为13:00/13:15/13:30/13:45。
- 后续的interval计算会自然生成上述13点时段的时间,导致数组中出现重复的
Date。 - 由于
ForEach使用id: \.self作为元素唯一标识,重复的Date会被视为同一元素,不会重复渲染,最终网格中出现空白间隙。
解决方法
方法一:避免生成重复Date(推荐)
修改dates数组的生成逻辑,直接跳过12点时段的时间,从根源上消除重复:
let dates: [Date] = (0...34).compactMap { interval -> Date? in var components = Calendar.current.dateComponents([.day, .month, .year], from: Date()) components.hour = 7 components.minute = 30 guard var date = Calendar.current.date(from: components) else { return nil } date.addTimeInterval(Double(900 * interval)) // 直接过滤12点的时间,不加入数组 if Calendar.current.component(.hour, from: date) == 12 { return nil } return date }
方法二:优化按钮布局(让按钮占满列宽)
如果希望按钮填满网格列的宽度,让整体布局更整齐,可以给Capsule添加宽高约束:
Button { } label: { Capsule() .overlay { Text(text(for: date)) .foregroundStyle(.white) } .foregroundColor(.blue) .frame(height: 44) .frame(maxWidth: .infinity) // 让胶囊按钮占满列宽 }
方法三:使用索引作为唯一标识(不推荐,会显示重复按钮)
如果需要保留重复的时间按钮,可以用数组索引作为ForEach的id,确保每个元素都被渲染:
ForEach(Array(dates.enumerated()), id: \.offset) { index, date in Button { } label: { // 按钮内容保持不变 Capsule() .overlay { Text(text(for: date)) .foregroundStyle(.white) } .foregroundColor(.blue) .frame(height: 44) } }
内容的提问来源于stack exchange,提问作者CompC
相关产品推荐
相关产品推荐

