How do I detect when user reaches the bottom of a ScrollView?

42 Views Asked by At

I have a search bar on top of the screen. I need to hide when scrolling down and unhide when scrolling up, which I achieved using this answer.

But I found one issue with the calculation of wholeSize and scrollViewSize. It is giving different values on different scrolls. Suppose I am scrolling down and I am at position y = 400 from origin, scrollViewSize = 740. Now again when I come back scrolling at this same position, y = 400, scrollViewSize = 789. The number is not exact, only for the inference.

I have already explored the answer above; the issue I'm facing is that sometimes, while on the bottom of the screen, the statement currentOffset >= scrollViewSize.height - wholeSize.height becomes false. My ScrollView bounces when it is on the bottom of the screen which I needed to be there. Here is a partial code snippet:

.background(GeometryReader {
    Color.clear.preference(key: ViewOffsetKey.self, value: -$0.frame(in: .named("scroll")).origin.y)
}).onPreferenceChange(ViewOffsetKey.self) { currentOffset in
    let offsetDifference: CGFloat = self.previousScrollOffset - currentOffset
    
    
    if ( abs(offsetDifference) > minimumOffset) {
        
        
        if currentOffset >= scrollViewSize.height - wholeSize.height {
            Utilities.DBLog(_object: "currentOffset \(currentOffset)")
            Utilities.DBLog(_object: "wholeSize.height \(wholeSize.height)")
            Utilities.DBLog(_object: "scrollViewSize.height \(scrollViewSize.height)")
            Utilities.DBLog(_object: "User has reached the bottom of the ScrollView.")
            DispatchQueue.main.async {
                withAnimation(.easeOut(duration: ZIAnimation.durationPoint6)) {
                    if show ?? false {
                        show = false
                    }
                }
            }
        }
        else
        if offsetDifference > 0 || self.previousScrollOffset < 0  {
            Utilities.DBLog(_object: "Is scrolling up toward top.")
            Utilities.DBLog(_object: self.previousScrollOffset)
            Utilities.DBLog(_object: "currentOffset \(currentOffset)")
            Utilities.DBLog(_object: offsetDifference)
            Utilities.DBLog(_object: "wholeSize.height \(wholeSize.height)")
            Utilities.DBLog(_object: "scrollViewSize.height \(scrollViewSize.height)")
            DispatchQueue.main.async {
                withAnimation(.easeOut(duration: ZIAnimation.durationPoint3)) {
                    if !(show ?? false) {
                        show = true
                    }
                }
            }
            
        } else if offsetDifference < 0 {
            Utilities.DBLog(_object: "Is scrolling down toward bottom.")
            Utilities.DBLog(_object: self.previousScrollOffset)
            Utilities.DBLog(_object: "currentOffset \(currentOffset)")
            Utilities.DBLog(_object: offsetDifference)
            Utilities.DBLog(_object: "wholeSize.height \(wholeSize.height)")
            Utilities.DBLog(_object: "scrollViewSize.height \(scrollViewSize.height)")
            DispatchQueue.main.async {
                withAnimation(.easeOut(duration: ZIAnimation.durationPoint6)) {
                    if show ?? false {
                        show = false
                    }
                }
            }
            
        }
        
        self.previousScrollOffset = currentOffset
    }
}
0

There are 0 best solutions below