Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting constant width on subview of UIStackView when axis is vertical

I have a UIScrollView that contains a UIStackView, and I add views to it and if the UIStackView needs more space than the screen has then it will scroll thanks to the UIScrollView.

I am able to set constant heights on the views, but I also need to set a specific width on them, so that they have a specific width and are also centered in the stack view.

Something like this, except the widthAnchor does not work.

import UIKit

class ViewController: UIViewController {

    let scrollView: UIScrollView = {
        let sv = UIScrollView()
        sv.translatesAutoresizingMaskIntoConstraints = false
        sv.backgroundColor = .gray
        return sv
    }()

    let stackView: UIStackView = {
        let sv = UIStackView()
        sv.translatesAutoresizingMaskIntoConstraints = false
        sv.axis = .vertical
        return sv
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(scrollView)

        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

        scrollView.addSubview(stackView)

        stackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
        stackView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
        stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

        stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true

        let view1 = UIView()
        view1.backgroundColor = .red

        let view2 = UIView()
        view2.backgroundColor = .blue

        let view3 = UIView()
        view3.backgroundColor = .green

        let view4 = UIView()
        view4.backgroundColor = .purple

        stackView.addArrangedSubview(view1)
        stackView.addArrangedSubview(view2)
        stackView.addArrangedSubview(view3)
        stackView.addArrangedSubview(view4)

        view1.heightAnchor.constraint(equalToConstant: 200).isActive = true
        view2.heightAnchor.constraint(equalToConstant: 300).isActive = true
        view3.heightAnchor.constraint(equalToConstant: 420).isActive = true
        view4.heightAnchor.constraint(equalToConstant: 100).isActive = true

        // This does not work.
//        view1.widthAnchor.constraint(equalToConstant: 40).isActive = true
    }

}
like image 582
Alex Avatar asked Dec 19 '22 03:12

Alex


1 Answers

The alignment property on a UIStackView determines how its layout works perpendicular to its axis. By default, a UIStackView has an alignment of fill. In constraint terms, fill is like adding a constraint to (in this case) the left and right edges of the stack view for each arranged subview. These implicit constraints are likely causing your problem. Solution: set stackView.alignment = either leading, center, or trailing depending on your desired effect.

like image 137
Connor Neville Avatar answered Dec 20 '22 17:12

Connor Neville