I have a UIView
like iPhone's Springboard. I have created it using a UIScrollView
and UIButtons
. I want to disable horizontal scrolling on said scrollview. I want only vertical scrolling. How do I accomplish this?

- 37,241
- 25
- 195
- 267

- 28,260
- 49
- 182
- 256
-
5You should change your title : you ask for horizontal in the question and vertical in the title. People find your questions later on search engines, so it still matters 2 years later :) – Julien Jun 18 '11 at 22:15
-
@RahulVyas The man above has a point. Changing the title will decrease any confusion for beginners who get here through a search engine (such as me ;) ). – SpacyRicochet Sep 12 '11 at 09:23
-
Have edited the title on the poster's behalf. (Though it is currently awaiting peer review before the edit will be visible.) – Duncan Babbage Sep 28 '11 at 12:02
15 Answers
You have to set the contentSize
property of the UIScrollView
. For example, if your UIScrollView
is 320 pixels wide (the width of the screen), then you could do this:
CGSize scrollableSize = CGSizeMake(320, myScrollableHeight);
[myScrollView setContentSize:scrollableSize];
The UIScrollView
will then only scroll vertically, because it can already display everything horizontally.

- 12,576
- 11
- 64
- 83

- 242,470
- 58
- 448
- 498
-
6Hi. This solution works really fine! Thanks for that. I tried setting the static width to 0. For me this works too. I don't know if there might be some side effects later. But if one doesn't know the size (i.e. universal code for iPhone and iPad) this works great! – JackPearse Apr 28 '11 at 10:32
-
5I think better to do CGSizeMake(0, myScrollableHeight), so horizontal scrolling disabled even if not all subviews showed. – LightNight Aug 29 '13 at 16:11
-
NB Setting one of the dimensions to 0 when using paging will cause VoiceOver to announce the page number as "page 1 of 1" regardless of the correct value – josef Jan 10 '14 at 01:09
-
1Instead of passing width as 320 hardcoded, we can pass like: CGSize scrollableSize = CGSizeMake(self.scrollview.frame.size.width, myScrollableHeight); [myScrollView setContentSize:scrollableSize]; – Mohit kumar Jul 06 '16 at 11:26
UPDATED: (After @EranMarom pointed out on his comment)
You can stop horizontal scrolling or vertical scrolling in the ScrollViewDelegate
Method.
Here it is how,
Stops Horizontal Scrolling:
If you want to scroll horizontally, then you need to increase the contentOffset.x. Preventing that stops the scrollview scroll in horizontal direction.
- (void)scrollViewDidScroll:(UIScrollView *)sender {
sender.contentOffset.x = 0.0
}
Stops Vertical Scrolling:
If you want to scroll vertically, then you need to increase the contentOffset.y. Preventing that stops the scrollview scroll in vertical direction.
- (void)scrollViewDidScroll:(UIScrollView *)sender {
sender.contentOffset.y = 0.0
}
Above code prevents the changes in x
and y
of a scrollview contentOffset
and it leads to stop the scrolling in scrollViewDidScroll:
method.

- 8,501
- 5
- 42
- 81
-
1I'm considering downvoting because this answer doesn't explain it's self you have just given code and that's it. Answer like that aren't very good. Good answer explain themselves, whilst experienced developers may understand this newer developers might not understand what's going on here. Not downvoted yet as giving the chance to improve. – Popeye Jun 09 '13 at 12:28
-
16This is sort of a hack, but it worked when all else failed. So +1, but use only as a last resort. – i_am_jorf Feb 20 '14 at 01:37
-
5I also use this delegate method, but I replace the body with a one-liner, e.g.: `scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);` to disable horizontal scrolling. I find it more readable, it's smaller, and there is no point doing the test for zero because there's virtually no overhead with code that runs this infrequently (i.e. a few tens of times per second max). – Echelon Sep 15 '14 at 13:07
-
because you're changing the contentOffset after "didscroll", not like before 'willscroll', and this is a hammer solution, but i myself didn't downvote, because 18 upvotes and the answer is 75, so it's not worthy to downvote – LolaRun Dec 09 '14 at 11:15
-
@LolaRun But the solution is all about the resetting the changed content offset in "didScroll" method. In "willScroll", there won't be any change in content offset which we need to catch. Makes sense? I understand you didn't downvote, But to help you agree with the concept. – Dinesh Raja Dec 09 '14 at 16:27
-
This approach interferes with UIScrollView's coasting and bouncing which completely changes the experience. It doesn't cleanly do the job of only restricting scrolling in a certain direction. – davew Nov 19 '15 at 23:03
-
@davew I don't get it. Do you want to prevent scrolling but bouncing? also above code doesn't interferes with other direction. – Dinesh Raja Nov 20 '15 at 07:20
-
2Even easier, use `scrollView.contentOffset.y = 0.0` to stop vertical scrolling and `scrollView.contentOffset.x = 0.0` to stop horizontal scrolling, in the `scrollViewDidScroll()` delegate function. However, I believe that making sure the `scrollView.contentSize` equals the `scrollView.frame.size` is a better (correct) solution. See @danbeaulieu answer. – emem Apr 04 '16 at 13:35
-
@EranMarom Thank you for pointing out. Not sure, if you can set 'y' position alone by now. But, above code is written a long time before. We couldn't set 'x' or 'y' property in content offset directly. The other answer you pointed out is obviously correct one. But will not work if the actual content placement is more than the scrollview size and if you used autolayout to calculate the content size. – Dinesh Raja Apr 04 '16 at 15:27
-
@DineshRaja Thanks, I did have problems using the contentSize solution in some cases (perhaps in cases the content size was reset later by the auto layouts mechanism). And yes, I mainly wanted to point out you can now set the x and y separately. – emem Apr 05 '16 at 14:33
-
@i_am_jorf You are right, this is a hack. But all else does not fail. We could just set the contentSize appropriately instead of using a hack. – Zia Apr 07 '16 at 19:16
since iOS7 use
self.automaticallyAdjustsScrollViewInsets = NO;
//and create you page scroller with 3 pages
self.pageView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.pageView setContentSize:CGSizeMake(self.view.frame.size.width*3, self.view.frame.size.height)];
[self.pageView setShowsVerticalScrollIndicator:NO];
[self.pageView setPagingEnabled:YES];
[self.view addSubview:self.pageView];

- 2,204
- 2
- 21
- 22
-
I don't think this will disable the scrolling behavior of a scrollview. Is it?? – Dinesh Raja Feb 12 '14 at 03:10
-
`self.collectionView.pagingEnabled = YES;` helped me to resolve problem with smooth scrolling (not dragging). The problem was in method `scrollViewWillEndDragging:` - targetContentOffset was the same as scrollView.contentOffset and page detection logic doesn't work properly. – sig May 20 '15 at 18:18
Swift solution
Create two outlets, one for your view and one for your scroll view:
@IBOutlet weak var myView: UIView!
@IBOutlet weak var scrollView: UIScrollView!
Then in your viewDidLayoutSubviews you can add the following code:
let scrollSize = CGSize(width: myView.frame.size.width,
height: myView.frame.size.height)
scrollView.contentSize = scrollSize
What we've done is collected the height and width of the view and set the scrollViews content size to match it. This will stop your scrollview from scrolling horizontally.
More Thoughts:
CGSizeMake takes a width & height using CGFloats. You may need to use your UIScrollViews existing height for the second parameter. Which would look like this:
let scrollSize = CGSize(width: myView.frame.size.width,
height: scrollView.contentSize.height)

- 2,164
- 1
- 20
- 25

- 19,406
- 19
- 101
- 135
-
What if you don't know the height or the width (universal device)? @danbeaulieu – Lukesivi Feb 08 '16 at 22:00
-
@lukesIvi "myView.frame.width" is dynamically pulling the width from the "myView" IBOutlet. – Dan Beaulieu Feb 08 '16 at 22:10
In my case, with Swift 4.2 you can use:
Disable vertical scroll:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
scrollView.contentOffset.y = 0.0
}
Disable horizontal scroll:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
scrollView.contentOffset.x = 0.0
}

- 2,086
- 25
- 35
In my case the width of the contentView was greater than the width of UIScrollView and that was the reason for unwanted horizontal scrolling. I solved it by setting the width of contentView equal to width of UIScrollView.
Hope it helps someone

- 1,010
- 12
- 23
-
-
This should be the chosen answer. Everything else is a distraction. Horizontal scrolling should not be happening when there is no horizontal content to scroll. – ScottyBlades Jun 06 '21 at 19:48
You can select the view, then under Attributes Inspector
uncheck User Interaction Enabled
.

- 1,403
- 2
- 19
- 35
Introduced in iOS 11 is a new property on UIScrollView
var contentLayoutGuide: UILayoutGuide
The documentation states that you:
Use this layout guide when you want to create Auto Layout constraints related to the content area of a scroll view.
Along with any other Autolayout constraints that you might be adding you will want to constrain the widthAnchor
of the UIScrollView
's contentLayoutGuide
to be the same size as the "frame". You can use the frameLayoutGuide
(also introduced in iOS 11) or any external width (such as your superView
's.)
example:
NSLayoutConstraint.activate([
scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.widthAnchor)
])
Documentation: https://developer.apple.com/documentation/uikit/uiscrollview/2865870-contentlayoutguide

- 799
- 5
- 18
@Gulfam Khan's answer is the correct one, I am adding imagery to help the concept get more visibility.
When we set the contentView to have equal width's with the Scroll view, if the multiplier is even slightly greater than 1:1, then we will get horizontal scrolling.
Here is what it produces:
If you do not want horizontal scrolling, you most likely do not have horizontal content that exceeds the width of the superview.
Therefore if you ensure the contentView width does not exceed the width of the scroll view, that will automatically resolve the problem as UIKit recognizes there is no horizontal content to scroll to. Like so:
Now you should only see vertical:

- 12,189
- 5
- 77
- 85
-
Worth checking your constraints. I'm not sure why the `multiplier` ends up as a decimal number, but this fixed it for me. – skymook Aug 10 '21 at 08:39
-
1I think when you set the width to be equal when dragging , we think we set it to be exactly equal but we actually set it to be nearly exactly equal and then we get 1.00003 baked in as a multiplier. It’s the imperfection of dragging getting baked in to your multiplier. – ScottyBlades Aug 10 '21 at 09:34
I struggled with this for some time trying unsuccessfully the various suggestions in this and other threads.
However, in another thread (not sure where) someone suggested that using a negative constraint on the UIScrollView worked for him.
So I tried various combinations of constraints with inconsistent results. What eventually worked for me was to add leading and trailing constraints of -32 to the scrollview and add an (invisible) textview with a width of 320 (and centered).
I had the tableview contentInset set in viewDidLoad (as below) that what causing the horizontal scrolling
self.tableView.contentInset = UIEdgeInsetsMake(0, 30, 0, 0);
Check if there are any tableview contentInset set for different reasons and disable it

- 11,885
- 4
- 72
- 54
Try This:
CGSize scrollSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, scrollHeight);
[scrollView setContentSize: scrollSize];

- 1,021
- 1
- 7
- 14
Disable horizontal scrolling by overriding contentOffset
property in subclass.
override var contentOffset: CGPoint {
get {
return super.contentOffset
}
set {
super.contentOffset = CGPoint(x: 0, y: newValue.y)
}
}

- 5,470
- 2
- 37
- 71
Once I did it replacing the UIScrollView with a UITableView with only 1 cell, it worked fine.

- 6,746
- 4
- 38
- 55