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

SwiftUI:如何准确检测LazyVGrid当前顶部的GridItem

问题:检测LazyVGrid的顶部可见行索引

我需要确定哪个GridItem处于x:0、y:0的位置,于是尝试用PreferenceKey和GeometryReader实现。我给每个GridItem添加了.overlay,仅在索引为0的GridItem上用GeometryReader包裹Color.clear,期望通过跟踪该GridItem的Y偏移量,除以单个GridItem的高度来计算当前顶部的项索引。

但这个方案只能部分工作:当索引为0的GridItem滚动到特定偏移量以上后,就无法读取到它的Y位置,数值固定为0.0,我推测这是视图复用导致的。目前只能读取到40以内的数值,但我需要能检测到LazyVGrid滚动到底部为止。

以下是我的代码:

struct DetectScrollPosition: View {
    
    let gridRowLayout = Array(repeating: GridItem(spacing: 0), count: 7)
    
    @State private var scrollPosition: Int = 0
    
    var body: some View {
        NavigationView {
            ScrollView (.vertical){
                LazyVGrid(columns: gridRowLayout, spacing: 0){
                    ForEach(0..<1092, id: \.self) { gridItemIndex in
                        Text("\(abs(gridItemIndex / 7))")
                            .overlay {
                                if gridItemIndex == 0 {
                                    GeometryReader { geometryProxy in
                                        Color.clear
                                            .updateViewsYPosition(geometryProxy)
                                        
                                    }
                                }
                            }
                    }
                }
                
                .onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
                    self.scrollPosition = abs(Int(value))
                }
                
            }
            
            .coordinateSpace(.named("scroll"))
            .navigationTitle("The Top Row is: \(scrollPosition)")
            .navigationBarTitleDisplayMode(.inline)
        }
        
    }
}

struct ScrollOffsetPreferenceKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
    }
}

extension View {
    func updateViewsYPosition(_ geometryProxy: GeometryProxy) -> some View {
        let offset = geometryProxy.frame(in: .named("scroll")).origin.y / geometryProxy.frame(in: .named("scroll")).height
        return self.preference(key: ScrollOffsetPreferenceKey.self, value: offset)
    }
    
    
}

效果演示图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 02:12:46