Limiting the scrollable area in UIScrollView

16,027

Solution 1

I would change the contentSize property of the scroll view to the size of the area you want the user to be able to scroll around in and adjust the frame.origin of the subview such the upper left boundary you want appears at (0, 0) relative to the scroll view. For example, if your view is 800 points tall and you want to show the bottom quarter, set the height of contentSize to 200 and set the y component of view.frame.origin to -600.

Solution 2

I've found something that works for me. It let's you scroll to point 0,0 but no further:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (scrollView.contentOffset.x <= -1) {
        [scrollView setScrollEnabled:NO];
        [self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
        [scrollView setScrollEnabled:YES];
    }
}

You could do the same for top, bottom or right (x or y)

Solution 3

a small improvement on Yoko's answer in Swift 4 will be

override func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
    if scrollView.contentOffset.y > 600 {
        let anim = UIViewPropertyAnimator(duration: 1, dampingRatio: 0.5) {
            scrollView.isScrollEnabled = false
            scrollView.setContentOffset(CGPoint(x: 0, y: 600), animated: false)
            scrollView.isScrollEnabled = true
        }
        anim.startAnimation()
    }
}

which will make the scrollview animate really similar to what its supposed to do. The slower drag when you are in the "bounce" area will not work and animation duration has to depend on the distance (not constant like here) if you want to be exact. You can also try to do this logic in scrollViewDidScroll and see how it differs. The key thing is that setContentOffset(_:,animated:) has to be with animated: false so that the UIViewPropertyAnimator's block can capture it and animate it

Share:
16,027
Mongus Pong
Author by

Mongus Pong

I am a coder and I code.

Updated on July 28, 2022

Comments

  • Mongus Pong
    Mongus Pong almost 2 years

    I have a UIScrollView that is scrolling a fairly large UIView.

    At certain times I want to limit the area the user can scroll around in. For example, I may only want to allow them to view the bottom quarter of the view.

    I am able to limit the area by overriding scrollViewDidScroll and then calling setContentOffset if the view has scrolled too far. But this way I can't get it bounce back as smoothly as the UIScrollView can naturally do when scrolling beyond the bounds of the UIView.

    Is there a better way to limit the scrollable area in a UIScrollView?

  • HM1
    HM1 over 12 years
    Your answer was just the right tip I needed to solve a similar problem I had. Basically the difference between the uiscrollview.frame.size and uiscrollview.contentsize becomes your allowed scrollable portion. You can play with the uiview that's placed in the uiscrollview any way you like to get the desired effect you want using the uiview.frame and uiview.size. Once you understand this, life is good. Happy scrolling! :)
  • Mongus Pong
    Mongus Pong almost 10 years
    The problem with this method is that you lose the 'bounce' - where you scroll beyond the region and the scroll gently snaps back when you let go.
  • Yoko
    Yoko almost 10 years
    Crap you're right, did not read properly. Still, maybe this can help somebody else.
  • Evgeny Aleksandrov
    Evgeny Aleksandrov about 8 years
    Here is example of solution that encapsulated similar logic: github.com/ealeksandrov/EARestrictedScrollView