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

如何让SwiftUI List的第一行像Apple Health应用一样撑满屏幕宽度

如何让SwiftUI List的第一行像Apple Health应用一样撑满屏幕宽度

嘿,这个需求我之前做健康类APP的时候也碰到过!Apple Health那种首行全屏、后面保持.insetGrouped风格List的布局,完全不用放弃List去折腾ScrollView+VStack,咱们直接在List里就能搞定,给你两种亲测有效的方案:

方案1:直接调整首行的内边距

这种方法最直接,适合首行内容比较简单的情况,只需要给第一行单独设置listRowInsets去掉左右内边距,再让内容撑满宽度就行:

struct HealthStyleSimpleList: View {
    var body: some View {
        List {
            // 首行:撑满屏幕宽度
            Text("你的健康概览")
                .font(.title.bold())
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding()
                .background(Color(.systemGray6))
                .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
                .listRowSeparator(.hidden) // 可选:隐藏首行和下面行的分隔线
            
            // 后面的行:保持.insetGrouped原生样式
            Section(header: Text("今日数据")) {
                HStack {
                    Text("步数")
                    Spacer()
                    Text("8,523")
                }
                HStack {
                    Text("活动能量")
                    Spacer()
                    Text("320 千卡")
                }
            }
            
            Section(header: Text("睡眠记录")) {
                HStack {
                    Text("昨晚睡眠时长")
                    Spacer()
                    Text("7小时23分")
                }
            }
        }
        .listStyle(.insetGrouped)
    }
}

这里的关键是:

  • listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)):彻底去掉首行的左右内边距
  • frame(maxWidth: .infinity):让内容强制撑满整个行宽
  • listRowSeparator(.hidden):如果不想首行和下面行有分隔线,可以把它隐藏掉,更贴近Health的风格

方案2:把首行作为List的头部(适合复杂内容)

如果你的首行需要放图表、多组文本或者其他复杂组件,把它作为List的头部来实现会更贴合List的原生结构,代码维护起来也更清晰:

struct HealthStyleComplexList: View {
    var body: some View {
        List {
            // 全屏头部内容:单独抽成子View,更易维护
            healthHeaderView
                .listRowInsets(EdgeInsets())
                .listRowBackground(Color.clear)
            
            // 后面的.insetGrouped风格内容
            Section(header: Text("活动目标")) {
                HStack {
                    Text("运动时长")
                    Spacer()
                    Text("45 / 60 分钟")
                }
                HStack {
                    Text("站立次数")
                    Spacer()
                    Text("12 / 12 次")
                }
            }
            
            Section(header: Text("健康指标")) {
                HStack {
                    Text("心率")
                    Spacer()
                    Text("72 bpm")
                }
                HStack {
                    Text("血氧饱和度")
                    Spacer()
                    Text("98%")
                }
            }
        }
        .listStyle(.insetGrouped)
    }
    
    // 单独定义头部View,方便修改样式和内容
    private var healthHeaderView: some View {
        VStack(alignment: .leading, spacing: 16) {
            Text("你的健康概览")
                .font(.title.bold())
            Text("今日活动达标率 75%")
                .font(.subheadline)
                .foregroundColor(.secondary)
            ProgressView(value: 0.75)
                .frame(height: 8)
        }
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(Color(.systemGray6))
    }
}

这种方式的好处是,头部内容可以单独维护,而且和后面的List分组衔接得更自然,完全是原生Apple Health的质感。

小提示

如果要让首行和后面的List无缝衔接,记得头部的背景色要和List的默认背景匹配,比如用Color(.systemGray6),这样看起来就像系统原生组件一样和谐~

备注:内容来源于stack exchange,提问作者Wojciech Konury

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:48:02