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

SwiftUI双轴滚动ScrollView嵌套LazyStack布局错乱如何解决

SwiftUI双轴ScrollView电子表格布局错乱问题

问题描述

在面向iPhone、iPad、Mac的SwiftUI跨平台项目中,使用同时开启.horizontal和.vertical双轴滚动的ScrollView实现类电子表格布局。ScrollView内部嵌套配置了pinnedViews: [.sectionHeaders, .sectionFooters]的LazyVStack,其中区头、区尾、内容单元格均各自包裹在LazyHStack中;采用懒加载堆栈是为了适配行列数据量增长时的性能需求,但双轴同时滚动时ScrollView会出现严重的布局错乱问题。

已尝试的无效方案

  • 自研懒加载水平堆栈,仅渲染可视范围内的单元格,动态计算设置前后内边距,未解决问题
  • 引入Introspect for SwiftUI库,为macOS端设置usesPredominantAxisScrolling属性、为iOS端设置isDirectionalLockEnabled属性,效果不符合预期
  • 实现手动滚动轴锁定逻辑:某一轴滚动时锁定另一轴,该方案在iOS端运行正常,但macOS端因缺少NSScrollViewDelegate回调、滚动事件通过NotificationCenter传递导致性能极差,无法投入使用

效果展示

提供iOS、macOS端的异常效果截图与录屏供参考:

  • iOS端异常截图:SwiftUI iOS端双轴滚动布局异常
  • macOS端异常截图:SwiftUI macOS端双轴滚动布局异常
  • iOS端异常效果录屏
  • macOS端异常效果录屏

复现代码

新建Multiplatform类型的SwiftUI项目后,将以下代码粘贴至ContentView.swift文件即可复现问题:

import SwiftUI

let numberOfColums: Int = 150
let numberOfRows: Int = 350

struct ContentView: View {
    var items: [[Item]] = {
        var items: [[Item]] = [[]]
        for rowIndex in 0..<numberOfRows {
            var row: [Item] = []
            for columnIndex in 0..<numberOfColums {
                row.append(Item(column: columnIndex, row: rowIndex))
            }
            items.append(row)
        }
        return items
    }()

    var body: some View {
        Group {
            ScrollView([.horizontal, .vertical]) {
                LazyVStack(alignment: .leading, spacing: 1, pinnedViews: [.sectionHeaders, .sectionFooters]) {
                    Section(header: Header()) {
                        ForEach(0..<items.count, id: \.self) { rowIndex in
                            let row = items[rowIndex]
                            LazyHStack(spacing: 1) {
                                ForEach(0..<row.count, id: \.self) { columnIndex in
                                    Text("\(columnIndex):\(rowIndex)")
                                        .frame(width: 100)
                                        .padding()
                                        .background(Color.gray.opacity(0.2))
                                }
                            }
                        }
                    }
                }
            }
            .edgesIgnoringSafeArea([.top])
        }
        .padding(.top, 1)
    }
}

struct Header: View {
    var body: some View {
        LazyHStack(spacing: 1) {
            ForEach(0..<numberOfColums, id: \.self) { idx in
                Text("Col \(idx)")
                    .frame(width: 100)
                    .padding()
                    .background(Color.gray)
            }
            Spacer()
        }
    }
}

struct Item: Hashable {
    let id: String = UUID().uuidString
    var column: Int
    var row: Int
}

求助诉求

希望确认该问题是否为SwiftUI ScrollView的已知Bug,寻求可落地的有效解决方案,若能实现滚动时单轴锁定的效果也可满足需求,当前实现无法投入生产使用,恳请提供可行思路。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 22:54:20