89

There is an option in IB to uncheck vertical scrolling on a scrollview, but it doesnt seem to work.

How can the scrollview be set to only scroll horizontally, and not vertically in the code rather than IB?

RK-
  • 12,099
  • 23
  • 89
  • 155
some_id
  • 29,466
  • 62
  • 182
  • 304
  • possible duplicate of [how to disable vertical scrolling of scrollview iphone?](http://stackoverflow.com/questions/1062693/how-to-disable-vertical-scrolling-of-scrollview-iphone) – Anurag Feb 23 '11 at 19:04

13 Answers13

138

since iOS7:

first: the content size width must be equal to the width of your scrollview

second: in your initWithNibName:

self.automaticallyAdjustsScrollViewInsets = NO;

That´s it.

some_id
  • 29,466
  • 62
  • 182
  • 304
Mirko Brunner
  • 2,204
  • 2
  • 21
  • 22
  • Wonderful solution. Worked like a charm. Will it affect the size of the rest of the views in my ViewController? (Buttons, Labels..) I mean, "self" is an UIViewController in my case – voghDev Dec 17 '14 at 09:23
  • @voghDev no it has no effects to the subviews in your scrollview. – Mirko Brunner Dec 17 '14 at 13:18
  • Amazing added this to the viewdidload method on my view controllers that were having issues. – StackRunner Jul 10 '15 at 11:25
  • if you're using navigationController and your scrollview is behind the navigationBar's title like mine use under viewDidLoad method. It solves. – EFE Jul 15 '15 at 10:53
  • 1
    You can achieve the same in the storyboard settings directly without any line of code. Just select the scroll view controller and uncheck the "Adjust Scroll View Insets" in the attribute inspector. – Morpheus78 May 22 '16 at 17:54
  • What about when your `UIScrollView` is inside a `UICollectionViewCell` for instance? – Skoua Nov 08 '16 at 11:41
  • For me, sending the `collectionView` to front of all views solved the issue – Husam Oct 02 '17 at 23:08
  • Thank you!!! I was going crazy! This should be false by default!!! – kaharoth Feb 25 '20 at 17:29
124

Try setting the contentSize's height to the scrollView's height. Then the vertical scroll should be disabled because there would be nothing to scroll vertically.

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,scrollView.frame.size.height);
ySgPjx
  • 10,165
  • 7
  • 61
  • 78
49

yes, pt2ph8's answer is right,

but if for some strange reason your contentSize should be higher than the UIScrollView, you can disable the vertical scrolling implementing the UIScrollView protocol method

 -(void)scrollViewDidScroll:(UIScrollView *)aScrollView;

just add this in your UIViewController

float oldY; // here or better in .h interface

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, oldY)];
    // or if you are sure you wanna it always on top:
    // [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, 0)];
}

it's just the method called when the user scroll your UIScrollView, and doing so you force the content of it to have always the same .y

meronix
  • 6,175
  • 1
  • 23
  • 36
  • 7
    God! Please DO NOT declare the oldY variable in .m file like `float oldY;` refer to the above code. That is a C-style variable symbol for per application, the variable MUST be declared as an instance member of controller class. – Itachi Nov 17 '15 at 04:07
21

Include the following method

-(void)viewDidLayoutSubviews{
    self.automaticallyAdjustsScrollViewInsets = NO;
}

and set the content size width of the scroll view equal to the width of the scroll view.

Jojodmo
  • 23,357
  • 13
  • 65
  • 107
Febin P
  • 366
  • 3
  • 9
  • 1
    This can also be done in Storyboard by selecting the View Controller and unchecking the property there – justColbs Aug 16 '16 at 21:25
  • 1
    I don't like this because it sets it for all scroll views... Wish you could be specific to one scroll view on the diagram w/o creating a new ScrollView class etc – visc Mar 18 '19 at 16:02
20

You need to pass 0 in content size to disable in which direction you want.

To disable vertical scrolling

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,0);

To disable horizontal scrolling

scrollView.contentSize = CGSizeMake(0,scrollView.contentSize.height);
Mani
  • 340
  • 2
  • 6
  • 1
    This will set the contentSize of the view to have 0 on the axis you set. ContentSize is referring to the size of the content, so we want to pass in the height of the screen to disable the vertical scrolling beyond that frame. the solution marked as correct, is correct. – some_id Feb 13 '16 at 07:55
  • This worked well for me. setting height as contentSize's height still got me vertical scrolling. – KoreanXcodeWorker Jul 15 '16 at 04:45
  • 1
    This did not work for me. Also tried self.automaticallyAdjustsScrollViewInsets – StackRunner Mar 21 '18 at 10:41
  • This is it! Setting to the height of the Scroll View didn't work for me, but this did – Echizzle Jun 10 '20 at 01:12
18

I updated the content size to disable vertical scrolling, and the ability to scroll still remained. Then I figured out that I needed to disable vertical bounce too, to disable completly the scroll.

Maybe there are people with this problem too.

bolonn
  • 191
  • 1
  • 5
  • You saved me. My contentSize and frame were the same and I could not for the life of me figure out what was wrong. Thanks a bunch!! – yuf Dec 13 '12 at 06:03
  • 2
    Your answer is why I love stackoverflow! :-) Holy smoke... this drove me nuts! You are right. It's the bounce effect. I want the bounce effect, but not when there is no need to scroll, so I'll be looking to disable/re-enable that effect now in code depending on whether there is a need to scroll. – Erik van der Neut Mar 16 '15 at 11:30
  • 2
    Okay, very easy to enable/disable the bounces on a UIScrollView at runtime. In my case I only care about the height of the scroll content and this did the trick: self.scrollView.bounces = (BOOL)(self.scrollView.contentSize.height > self.scrollView.frame.size.height); – Erik van der Neut Mar 16 '15 at 11:38
12
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x,0)];

}

you must have confirmed to UIScrollViewDelegate

aScrollView.delegate = self;
5

Just set the y to be always on top. Need to conform with UIScrollViewDelegate

func scrollViewDidScroll(scrollView: UIScrollView) {
        scrollView.contentOffset.y = 0.0
}

This will keep the Deceleration / Acceleration effect of the scrolling.

manuelsantos
  • 147
  • 2
  • 3
4

On iOS 11 please remember to add the following, if you're interested in creating a scrollview that sticks to the screen bounds rather than a safe area.:

if (@available(iOS 11.0, *)) {
    [self.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}
Michael
  • 1,285
  • 18
  • 31
2

A lot of answers include setting the contentOffset to 0. I had a case in which I wanted the view inside the scrollView to be centered. This did the job for me:

public func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = -scrollView.contentInset.top
}
regina_fallangi
  • 2,080
  • 2
  • 18
  • 38
1

From iOS11 one can use the following property

let frameLayoutGuide: UILayoutGuide

If you set constraints for frameLayoutGuide.topAnchor and frameLayoutGuide.bottomAnchor to the same anchors of some subview of your scrollView then vertical scroll will be disabled and the height of the scrollView will be equal to the height of its subview.

malex
  • 9,874
  • 3
  • 56
  • 77
1

The most obvious solution is to forbid y-coordinate changes in your subclass.

override var contentOffset: CGPoint {
  get {
    return super.contentOffset
  }
  set {
    super.contentOffset = CGPoint(x: newValue.x, y: 0)
  }
}

This is the only suitable solution in situations when:

  1. You are not allowed or just don't want to use delegate.
  2. Your content height is larger than container height
iWheelBuy
  • 5,470
  • 2
  • 37
  • 71
  • 1
    This is the best answer! Should be selected as solution! Thank you mate you saved my day! – imike Dec 13 '20 at 23:27
  • @imike my favorite solution is to use swizzling (: Check out the https://github.com/iwheelbuy/UIPanGestureRecognizerDirection repo – iWheelBuy Dec 19 '20 at 16:25
0

I think you can

  1. set directionalLockEnabled to true
  2. set the contentView's width equals to superView's width.

That should work.

Jerome Li
  • 1,492
  • 14
  • 20