0

I have seen several questions like this but none of the answers have managed to fix it for me.

I have a view at the bottom of the screen that contains a scrollView that contains a stackView that will be populated with buttons.

My view is built programmatically like so:

import UIKit

class BottomBar: UIView {

    typealias BindTap = ((String) -> Void)?

    private let scrollView = UIScrollView()
    private let buttonsStackView = UIStackView()

    var onTap: BindTap

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setUpViews()
        setUpLayout()
    }

    private func setUpViews() {
        backgroundColor = .cyan

        scrollView.backgroundColor = .red

        buttonsStackView.backgroundColor = .green

        buttonsStackView.alignment = .fill
        buttonsStackView.distribution = .equalSpacing
        buttonsStackView.axis = .horizontal
        buttonsStackView.spacing = 5

        scrollView.addSubview(buttonsStackView)
        addSubview(scrollView)
    }

    private func setUpLayout() {
        buttonsStackView.pinToSuperview(edges: [.top, .bottom, .left, .right],
                                        constant: 5,
                                        priority: .defaultHigh)
        scrollView.pinToSuperview(edges: [.top, .bottom, .left, .right],
                                  constant: 0,
                                  priority: .defaultHigh)
    }

    func addModelButtons(models: [Model]) {

        models.forEach { model in
            let modelButton = UIButton()
            modelButton.backgroundColor = .lightGray
            modelButton.setTitle(model.fileName, for: .normal)
            modelButton.addTarget(self, action: #selector(modelButtonTapped), for: .touchUpInside)

            buttonsStackView.addArrangedSubview(modelButton)

            if let first = models.first,
                first.fileName == model.fileName {
                updateSelectedButtonColor(modelButton)
            }
        }
    }

    @objc private func modelButtonTapped(button: UIButton) {
        guard let modelName = button.titleLabel?.text else { return }
            onTap?(modelName)
            resetButtonColors()
            updateSelectedButtonColor(button)
    }

    private func resetButtonColors() {
        for case let button as UIButton in buttonsStackView.subviews {
            button.backgroundColor = .lightGray
        }
    }

    private func updateSelectedButtonColor(_ button: UIButton) {
        button.backgroundColor = .darkGray
    }
}

I cant see what is missing. I've added a picture so you can see that the stackView is wrapping around the buttons and not filling the scrollview.

Any help would be great. Im sure its a simple fix i just cant see it!

picture

Wrumble
  • 231
  • 1
  • 5
  • 15

1 Answers1

3

Here's the thing to understand about scrollViews. Unless you give the content area of a scrollView an explicit size, it will determine its size from its subviews.

In your case, you've told it that your stackView is 5 points away from the edges of the scrollView. That ties the size of the stackView to the size of the content area of the scrollView. At this point, the stackView is controlling the size of the scrollable area of the scrollView. Since your stackView only has 2 buttons, the stackView shrinks to the size of those two buttons and the scrollable area of the scrollView is 10 wider than that. Since the buttons are small, this does not fill the screen.

What you want is that the buttons stretch to fill the apparent size of the scrollView. In order for that to happen, you need to tell Auto Layout that the stackView's width must be greater than or equal to the width of the scrollView - 10.

Add this constraint after scrollView.addSubview(buttonsStackView):

buttonsStackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor, multiplier: 1, constant: -10).isActive = true
vacawama
  • 150,663
  • 30
  • 266
  • 294
  • That's great, thank you so much! If there are two buttons they are now pinned to the left and right of the view. do you know how i can make the spacing between them and the edge equal? – Wrumble Jan 17 '18 at 13:51