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

SwiftUI ScrollView在LazyVStack嵌套LazyVGrid分页加载时自动滚动到底部问题

问题根因

  • 两层懒加载容器(LazyVStack嵌套LazyVGrid)同时工作时,SwiftUI布局系统无法正确计算内容高度变化后的滚动偏移量,会默认将滚动位置对齐到内容底部
  • 缺少加载状态判断,ProgressView可见就会触发加载逻辑,自动滚到底部后ProgressView持续可见,形成无限加载死循环
  • iOS 15及以上版本的ScrollView默认会在内容更新时尝试保持当前可见视图的位置,底部ProgressView属于动态插入的视图,会被系统判定为需要保持可见,导致滚动偏移被强制拉到底部

修复方案

方案1:新增加载状态判断,避免重复触发加载

在你的collection模型中新增isLoading布尔属性,网络请求发起时设为true,请求完成(无论成功失败)设为false,修改ProgressView的触发逻辑:

if self.collection.hasMore && !self.collection.isLoading
{
    HStack
    {
        Spacer()
        ProgressView()
        Spacer()
    }
    .padding(.top, 40)
    .onAppear { self.collection.load(next: 20) }
}

该修改可以快速解决无限加载的问题,即使滚动位置被拉到底部,也不会重复发起请求。

方案2:移除冗余的LazyVStack嵌套,避免布局冲突

LazyVGrid本身已经具备懒加载能力,不需要额外嵌套LazyVStack,直接将所有内容放到ScrollView下即可,布局逻辑会大幅简化:

ScrollView
{
    LazyVGrid(columns: self.columns, spacing: 20.0)
    {
        if let products = self.collection.products,
            products.count > 0
        {
            ForEach(products)
            { inProduct in
                NavigationLink(destination: ProductDetailsContainerView(searchResult: WNProductSearchResult(product: inProduct)))
                {
                    ProductListingCell(imageURL: inProduct.imageURL,
                                        title: inProduct.name,
                                        listingCount: inProduct.availableCount,
                                        price: inProduct.marketPrice)
                }
            }
        }
    }
    .padding(20)
    
    if let products = self.collection.products,
        products.count == 0
    {
        self.emptyDisplay
            .padding(20)
    }
    
    if self.collection.hasMore && !self.collection.isLoading
    {
        HStack
        {
            Spacer()
            ProgressView()
            Spacer()
        }
        .padding(.top, 40)
        .onAppear { self.collection.load(next: 20) }
    }
}

方案3:固定ScrollView滚动行为(iOS 16+支持)

如果需要保留LazyVStack嵌套结构,可以给ScrollView添加明确的滚动行为修饰符,禁止系统自动调整滚动偏移:

ScrollView
{
    // 原有内容不变
}
.scrollTargetBehavior(.custom)
.scrollBounceBehavior(.basedOnSize)
.automaticallyAdjustsScrollIndicatorInsets(false)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 02:36:05