ios – Trying to detect which GridItem is at top of view SwiftUI


I am trying to ascertain which GridItem would effectively be at position x:0, y:0.
To achieve this I am simply trying to use a preferenceKey and GeometryReader.
I am adding an .overlay to my GridItems and on the GridItem at gridItemIndex 0 adding the GeometryReader around a Color.clear. My expected logic is to track the Y position of that GridItem. Then by dividing that Y offset by the height of each GridItem I will get which item is currently at the top.

I have this working to a point. Once the GridItem at index “gridItemIndex” position 0 is above a certain offset it is no longer read and the y position rests to 0.0. My assumption for this is due to the view being reused?

Currently I am not getting the reading above 40 but I need to get until the bottom of the LazyVGrid appears.

Here is my code

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)
    }
    
    
}

apologies for poor gif image
enter image description here

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img