3
votes

I have a UIScrollView. It has a stack view. And this stack view contains 12 buttons. (Horizontal scroll view)

Stackview constraints :- top,leading,trailing,bottom to the scroll view and equal widths to the scroll view.

My problem is every time when I run, stack view width limits to the scroll view width and buttons are too small acording to the width of the stack view and my scroll view is not scrollable.

How to make this scrollable

3
Do you have a contentview inside the scrollview or are you adding the stackview directly to to the scrollview? See Apple's Guide to working with scrollviews - TheBaj
no I dont have a content view,, im adding the stack view directly into the scroll view @TheBaj - user1960169
Well, don't do that. Read the guide and follow the steps and you should be fine. - TheBaj
@TheBaj - UIStackViews work great when added directly to a scroll view - just have to set the constraints properly. - DonMag
Right, but if he's going to add more content to the scrollview than just the stackview, it would be better to work with a content view - TheBaj

3 Answers

12
votes

Step-by-Step for setting this up in IB / Storyboards...

  1. Add a view - height 50 leading/top/trailing - blue background

enter image description here

  1. add a scrollview to that view - pin leading/top/trailing/bottom to 0 - set scrollview background to yellow so we can see where it is

enter image description here

  1. add a button to the scroll view

enter image description here

  1. duplicate it so you have 12 buttons

enter image description here

  1. group them into a stack view, and set the stack view's constraints to 0 leading/top/trailing/bottom

enter image description here

  1. and set the stack view's distribution to "equal spacing"

enter image description here

  1. result running in simulator (with no code at all):

enter image description here

and the buttons scroll left and right... no code setting of .contentSize...

3
votes

So you want this:

demo

Here's how I did it in Xcode 8.3.3.

  1. New Project > iOS > Single View Application.

  2. Open Main.storyboard.

  3. Drag a scroll view into the scene.

  4. Pin top, leading, and trailing of the scroll view to 0. Set height to 30.

    scroll view constraints

  5. Drag a horizontal stack view into the scroll view.

  6. Pin all four edges of the stack view to 0.

    stack view constraints

  7. Set stack view spacing to 4.

  8. Drag twelve buttons into the stack view.

  9. Set target device to iPhone SE.

  10. Build & run.

Resulting document outline:

document outline

2
votes

If you make your Stackview width equal to the scrollview width, then that's all you'll get, and of course it won't scroll.

Don't give your Stackview a width constraint... let the buttons "fill it out".


Edit: Here is a simple example that you can run directly in a Playground page:

import UIKit
import PlaygroundSupport

class TestViewController : UIViewController {

    let scrollView: UIScrollView = {
        let v = UIScrollView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .cyan
        return v
    }()

    let stackView : UIStackView = {
        let v = UIStackView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.axis = .horizontal
        v.distribution = .equalSpacing
        v.spacing = 10.0
        return v
    }()


    override func viewDidLoad() {
        super.viewDidLoad()

        // add the scroll view to self.view
        self.view.addSubview(scrollView)

        // constrain the scroll view to 8-pts on each side
        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8.0).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0).isActive = true
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8.0).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true


        // add the stack view to the scroll view 
        scrollView.addSubview(stackView)

        // constrain the stackview view to 8-pts on each side
        //   this *also* controls the .contentSize of the scrollview
        stackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 8.0).isActive = true
        stackView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 8.0).isActive = true
        stackView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: -8.0).isActive = true
        stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -8.0).isActive = true

        // add ten buttons to the stack view
        for i in 1...10 {

            let b = UIButton()
            b.translatesAutoresizingMaskIntoConstraints = false
            b.setTitle("Button \(i)", for: .normal)
            b.backgroundColor = .blue
            stackView.addArrangedSubview(b)

        }

    }

}

let vc = TestViewController()
vc.view.backgroundColor = .yellow
PlaygroundPage.current.liveView = vc