[ios] How to disable horizontal scrolling of UIScrollView?

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?

This question is related to ios objective-c uiscrollview

The answer is


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.


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


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
}

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];

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


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


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.


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).


Once I did it replacing the UIScrollView with a UITableView with only 1 cell, it worked fine.


Try This:

CGSize scrollSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, scrollHeight);
[scrollView setContentSize: scrollSize];

Use this single line.

self.automaticallyAdjustsScrollViewInsets = NO;


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)
  }
}

You can select the view, then under Attributes Inspector uncheck User Interaction Enabled .


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)

Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to objective-c

Adding a UISegmentedControl to UITableView Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Warp \ bend effect on a UIView? Use NSInteger as array index Detect if the device is iPhone X Linker Command failed with exit code 1 (use -v to see invocation), Xcode 8, Swift 3 ITSAppUsesNonExemptEncryption export compliance while internal testing? How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem? Change status bar text color to light in iOS 9 with Objective-C

Examples related to uiscrollview

How can I mimic the bottom sheet from the Maps app? Is it possible for UIStackView to scroll? Set UITableView content inset permanently UIScrollView Scrollable Content Size Ambiguity How to use UIScrollView in Storyboard Get UIScrollView to scroll to the top How to scroll UITableView to specific position Disabling vertical scrolling in UIScrollView How do I auto size a UIScrollView to fit its content UIScrollView not scrolling