Search code examples
iosswiftuiscrollview

iOS: UIScrollView not samples all values


I would like to know specifically when the offset of the scrollView reaches the center of the page. Unfortunately scrollViewDidScroll does not samples all the values. So I am not entering the if every time I pass the center of the screen. How can I overcome this?

func scrollViewDidScroll(_ scrollView: UIScrollView) {

        let page = Int(scrollView.contentOffset.x / scrollView.frame.size.width)
        let offsetInPage = (scrollView.contentOffset.x / scrollView.frame.size.width) - CGFloat(page)

        if offsetInPage == 0.5 { // Does not called every time

            toggleColors()
        }
}

Solution

  • contentOffset is updated by handling touch gesture, which couldn't be done continuously because it's not like you get messages from touch screen on every change but instead system is checking state of the touch screen in some loop. In this case it's runloop. So there could be some changes that happen between runloop iterations and are not caught by the app. Theoretically in some cases gap could be even more than whole page.

    So it's better to check, what area is visible now, and calculate what color should be applied when this area is visible rather than waiting for some exact value of contentOffset to appear

    According to your code seems like you just want to switch colors when user scrolls so that all odd pages would have one color and all the even pages - another. If so, I'd do it like that:

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
    
        let page = Int(scrollView.contentOffset.x / scrollView.frame.size.width)
        let isOddPage = (page % 2 == 1)
        let offsetInPage = (scrollView.contentOffset.x / scrollView.frame.size.width) - CGFloat(page)
    
        if (isOddPage && offsetInPage < 0.5) || (!isOddPage && offsetInPage >= 0.5) {
            switchToOddColor()
        } else {
            switchToEvenColor()
        }
    }
    

    Or something like that. Maybe condition is more complex in your case and maybe you have more than just two colors, but the strategy is the same.

    It's also usefull to check if colors are not already set to needed value inside switchToOddColor and switchToEvenColor to avoid doing extra job.