iosswiftuikituistackview

UIStackView spacing seems very small


I'm trying to brush up on my UIKit and I can't figure out why my stack view spacing is so small when trying to add some custom views inside it. I've tried this stack view size on some of my past projects and they aren't the same, meaning on my other projects the stack view spacing shows the expected spacing for a value of 10, vs when I do a spacing of 10 on the code below there is hardly any.

class ViewController: UIViewController {
    private lazy var vStackView: UIStackView = {
        let stack = UIStackView(arrangedSubviews: [customButtonOne, customButtonTwo])
        stack.translatesAutoresizingMaskIntoConstraints = false
        stack.axis = .vertical
        stack.distribution = .fill
        stack.spacing = 10
        return stack
    }()
        
    private lazy var customButtonOne: CustomView = {
        let button = CustomView()
        return button
    }()
    
    private lazy var customButtonTwo: CustomView = {
        let button = CustomView()
        button.buttonView.setTitle("This is button two", for: .normal)
        return button
    }()
    
    init() {
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configure()
    }
    
    func configure() {
        view.addSubview(vStackView)


        NSLayoutConstraint.activate([
            vStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            vStackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
    }
}

This is what's inside the custom button view:

class CustomView: UIView {
    lazy var buttonView: UIButton = {
        let button: UIButton = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.backgroundColor = .systemBlue
        button.setTitle("Hello World", for: .normal)
        button.layer.cornerRadius = 8
        //button.configuration = buttonConfig
        return button
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        translatesAutoresizingMaskIntoConstraints = false
        addSubview(buttonView)
        setupView()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupView() {
        NSLayoutConstraint.activate([
            buttonView.centerXAnchor.constraint(equalTo: centerXAnchor),
            buttonView.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
    }
}

enter image description here


Solution

  • The problem is that CustomView has zero size. The stack view is essentially laying out two "points" with a spacing of 0, so the two "points" are 10pt apart, and the buttons are centered on those points.

    You used let button = CustomView() to create a CustomView. This gives it a frame of (0, 0, 0, 0). You can still see the buttons even though CustomView has zero size, because clipsToBounds is false.

    You can override intrinsicContentSize in CustomView, to be the same as that of the button:

    override var intrinsicContentSize: CGSize {
        buttonView.intrinsicContentSize
    }
    

    The stack view will use this to resize your CustomViews.