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

SwiftUI中如何为List内ForEach中的元素添加间距?

SwiftUI List Section内训练组VStack添加自定义分隔间距

我有一个包含Section的List结构:

VStack {
    List {
        Section(header: Text("Workout Details")) {}
    }
}

在"Exercises" Section中,我通过ForEach将每个训练组(set)放入独立的VStack中渲染:

Section(header: Text("Exercises")) {
    if let exercises = workout.exercises?.sorted(by: { $0.date < $1.date }) {
        ForEach(exercises){ exercise in
            if let exercisesets = exercise.sets {
                ForEach(exercisesets) { set in
                    // 想要在每个VStack之间添加20像素的间隔
                    VStack {
                        Text("\(exercise.exerciseName.name)")
                        HStack {
                            Text("\(set.weight)")
                            Text("\(set.reps)")
                        }
                    }
                }
            }
        }
        .onDelete(perform: delete)
    } 
    else {
        Text("No Exercises Yet")
    }
}

需求是给这些VStack之间添加灰色的分隔间距(每个训练组元素之间用灰色块隔开)。我尝试给VStack添加.padding(.bottom, 50),但效果不符合预期——当前渲染效果和期望的分隔样式有明显差距。

解决方案

方法1:添加自定义分隔视图

在每个VStack后插入一个灰色半透明的分隔块,同时跳过最后一个元素的分隔,避免多余的间距:

Section(header: Text("Exercises")) {
    if let exercises = workout.exercises?.sorted(by: { $0.date < $1.date }) {
        ForEach(exercises){ exercise in
            if let exercisesets = exercise.sets {
                ForEach(exercisesets) { set in
                    VStack {
                        Text("\(exercise.exerciseName.name)")
                        HStack {
                            Text("\(set.weight)")
                            Text("\(set.reps)")
                        }
                    }
                    // 仅给非最后一个元素添加分隔
                    if set != exercisesets.last {
                        Color.gray.opacity(0.2)
                            .frame(height: 20)
                            .padding(.horizontal, 16)
                    }
                }
            }
        }
        .onDelete(perform: delete)
    } 
    else {
        Text("No Exercises Yet")
    }
}
.listRowSeparator(.hidden) // 隐藏List默认的行分隔线

方法2:通过List行样式优化

隐藏List默认分隔线,给每个VStack添加背景和圆角,配合行内边距实现卡片式分隔效果:

Section(header: Text("Exercises")) {
    if let exercises = workout.exercises?.sorted(by: { $0.date < $1.date }) {
        ForEach(exercises){ exercise in
            if let exercisesets = exercise.sets {
                ForEach(exercisesets) { set in
                    VStack {
                        Text("\(exercise.exerciseName.name)")
                        HStack {
                            Text("\(set.weight)")
                            Text("\(set.reps)")
                        }
                    }
                    .padding()
                    .background(Color.white)
                    .cornerRadius(8)
                }
            }
        }
        .onDelete(perform: delete)
        .listRowSeparator(.hidden) // 隐藏默认行分隔线
        .listRowInsets(EdgeInsets(top: 0, leading: 16, bottom: 10, trailing: 16)) // 控制行内边距,调整元素间距
    } 
    else {
        Text("No Exercises Yet")
    }
}

为什么直接加padding效果不好?

List的行本身带有默认的内边距和分隔样式,直接给VStack添加.padding(.bottom)会和行的默认样式叠加,导致间距过大或背景区域延伸,无法实现精准的灰色分隔块效果。通过隐藏默认分隔线并自定义分隔视图或调整行样式,才能达到预期的视觉效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 18:23:12