24

I have a UIScrollView and I want it to be able to scroll in both directions (it currently does) but only one at a time. So, for instance, if you start scrolling it horizontally, it won't move vertically at all until you let go and start moving it vertically. How could I go about doing this?

Letrstotheprez
  • 622
  • 1
  • 5
  • 11

4 Answers4

62

Set the directionalLockEnabled property to YES. From the Apple docs:

If this property is NO, scrolling is permitted in both horizontal and vertical directions. If this property is YES and the user begins dragging in one general direction (horizontally or vertically), the scroll view disables scrolling in the other direction. If the drag direction is diagonal, then scrolling will not be locked and the user can drag in any direction until the drag completes. The default value is NO

Scott Berrevoets
  • 16,921
  • 6
  • 59
  • 80
  • 2
    Huh, I set that property in IB but it didn't work. It only worked programmatically. Thanks! – Letrstotheprez Jun 12 '12 at 17:49
  • I added this to: - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView worked for me. And added: scrollView.directionalLockEnabled in the function. When I read this answer it took me a bit of time to realise what I was adding the directionLockEnabled to and where I was adding it – sam_smith Jun 18 '14 at 06:40
  • 1
    `directionalLockEnabled` has been renamed to `isDirectionalLockEnabled` – Witek Bobrowski Apr 17 '21 at 20:59
7

The accepted answer for this question is not entirely correct. According to the current documentation for directionalLockEnabled (as quoted in the original answer) :

If the drag direction is diagonal, then scrolling will not be locked and the user can drag in any direction until the drag completes.

I've found this to be the case myself. If the initial direction of dragging is closer to a 45-degree angle between x and y axes, directional locking fails. If you drag more-or-less horizontally or vertically, locking activates.

For one way to accomplish true uni-axial locking, see this link: http://bogdanconstantinescu.com/blog/proper-direction-lock-for-uiscrollview.html

Ash
  • 9,064
  • 3
  • 48
  • 59
2

the simple way to achieve this is set the directionalLockEnabled to YES and implement the UIScrollerView delegate like this

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.contentOffset.x != 0 &&
        scrollView.contentOffset.y != 0) {
        scrollView.contentOffset = CGPointMake(0, 0);
    }
}
Munawir
  • 3,346
  • 9
  • 33
  • 51
Joe xi
  • 21
  • 1
1

This worked for me based on @Joe xi answer. Swift 3.0

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if scrollView.contentOffset.x != 0 && scrollView.contentOffset.y != 0 {
        scrollView.contentOffset = CGPoint(x: 0, y: 0)
    }
}
Victor Camargo
  • 374
  • 9
  • 16