Disable horizontal scroll in UIScrollView with autolayout
1) Horizontal scroll enables automatically when the content width in scrollView more than width of scrollView. Therefore, in order to avoid horizontal scrolling is necessary to make width of the content inside scrollView less than or equal to scrollView width.
Leading space
and trailing space
can't set specific width to views, they just stretch them. In regular views, they no stretch for more than width of view, but scrollView is a special view, actually, with an infinite content width. Therefore, trailing space
and leading space
constraints in scrollView change the width of views to their maximum possible values (In case with UILabel you can see resize to fit the text).
To avoid horizontal scrolling, you need to set specific width of each view, less than or equal to scrollView width. Specific width of views may be set with width constraints
.
Instead of setting each view width, much better to add a view–container and set width to it, and inside it place the views as needed.
Views hierarchy:
View -> ScrollView -> ContainerView -> UILabel -> UILabel -> ... other views that you need
Autolayout constraints:
ScrollView -> leading space to View : 0 -> trailing space to View : 0 -> top space to View : 0 -> bottom space to View : 0Container View -> leading space to ScrollView : 0 -> trailing space to ScrollView : 0 -> top space to ScrollView : 0 -> bottom space to ScrollView : 0 -> width equal to ScrollView : 0
To set width equal constraint
ctrl+drag from containerView
to scrollView
.
2) Vertical scroll is dependent on the total height of content. Blank space can be, if the last element inside containerView
has a large value of the bottom space to superview
.
Or do you mean bounce effect? You can disable vertical bounce of scrollView.
You can also easily do this in code. In my case, I have a UIStackView
that's the only subview of a UIScrollView
// Create the stack viewlet stackView = UIStackView()stackView.translatesAutoresizingMaskIntoConstraints = false// Add things to the stack view....// Add it as a subview to the scroll viewscrollView.addSubview(stackView)// Use auto layout to pin the stack view's sides to the scroll viewNSLayoutConstraint.activate([ stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: stackView.trailingAnchor), stackView.topAnchor.constraint(equalTo: scrollView.topAnchor), scrollView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor)])// Now make sure the thing doesn't scroll horizontallylet margin: CGFloat = 40scrollView.contentInset = UIEdgeInsets(top: margin, left: margin, bottom: margin, right: margin)scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = truelet stackViewWidthConstraint = stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)stackViewWidthConstraint.constant = -(margin * 2)stackViewWidthConstraint.isActive = true
The NSLayoutConstraint.activate
bit is taken from Dave DeLong's excellent UIView extension here: https://github.com/davedelong/MVCTodo/blob/master/MVCTodo/Extensions/UIView.swift#L26