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

SwiftUI如何在List上方添加可滑出屏幕边缘的水平轮播

SwiftUI 复刻Watch应用顶部水平轮播边缘截断问题修复

问题描述

尝试复刻苹果原生Watch应用布局:页面顶部为水平滚动轮播区域,下方搭配List列表组件。当前代码运行后,第一个Section内的水平轮播滚动到屏幕边缘时会被截断,无法实现轮播内容滑出屏幕边缘的预期效果。
当前效果截图

问题复现代码

let data: [String] = (0..<25).map { "Item \($0)" }
let data2: [String] = (0..<3).map { "Item \($0)" }

NavigationView {
    List {
        Section {
            ScrollView(.horizontal) {
                HStack {
                    ForEach(data) { element in
                        VStack {
                            Text(element)
                        }
                        .padding()
                        .background(Color(.secondarySystemBackground))
                        .cornerRadius(10)
                    }
                }
            }
        }
        .listRowBackground(Color.clear)
        .listRowInsets(.init())
        Section("Section 1") {
            ForEach(data2) { element in
                NavigationLink {
                    Text("Destination")
                } label: {
                    Label(element, systemImage: "calendar.circle.fill")
                }
            }
        }
    }
    .searchable(text: .constant(""), placement: .navigationBarDrawer(displayMode: .always))
    .navigationTitle("Watch")
}

目标参考效果

原生应用参考图

问题原因

截断问题来自两个系统默认行为:

  • 默认InsetGrouped样式的List行自动开启子视图裁剪,超出行边界的内容会被直接裁切
  • 水平ScrollView未做边距适配,初始内容位置和原生布局不对齐,且滚动视图自身默认裁剪超出边界的内容

修复后完整代码

let data: [String] = (0..<25).map { "Item \($0)" }
let data2: [String] = (0..<3).map { "Item \($0)" }

NavigationView {
    List {
        Section {
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 12) {
                    ForEach(data, id: \.self) { element in
                        VStack {
                            Text(element)
                        }
                        .padding()
                        .background(Color(.secondarySystemBackground))
                        .cornerRadius(10)
                    }
                }
                .padding(.horizontal, 16)
            }
            .scrollClipDisabled() // iOS17及以上使用,低版本可替换为.clipped(false)
            .frame(height: 100) // 根据卡片实际高度调整
        }
        .listRowBackground(Color.clear)
        .listRowInsets(.init(top: 0, leading: 0, bottom: 0, trailing: 0))
        .clipped(false)
        Section("Section 1") {
            ForEach(data2, id: \.self) { element in
                NavigationLink {
                    Text("Destination")
                } label: {
                    Label(element, systemImage: "calendar.circle.fill")
                }
            }
        }
    }
    .listStyle(.insetGrouped)
    .searchable(text: .constant(""), placement: .navigationBarDrawer(displayMode: .always))
    .navigationTitle("Watch")
}

关键调整说明

  • 给轮播所在行添加.clipped(false),关闭List行默认的边界裁剪,允许轮播内容滚动时滑出屏幕边缘
  • 给ScrollView添加.scrollClipDisabled(),关闭滚动视图自身的内容裁剪,避免滚动过程中边缘裁切
  • 给轮播内容容器HStack添加16pt水平内边距,让第一个卡片和下方列表内容左对齐,匹配原生布局
  • 给ScrollView设置固定高度,避免行高自适应异常
  • 隐藏水平滚动条,匹配原生应用交互效果
  • 给ForEach添加id: \.self,修正原代码中字符串元素未遵循Identifiable协议的编译问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 02:30:59