2

My StackView that I am making programmatically is looking like this:

Two Subviews:

Three Subviews:

Four Subviews:

This is my code:

    cameraButton.setImage(UIImage(named: "blueCamera"), for: .normal)
    cameraButton.addTarget(self, action: #selector(cameraTapped), for: .touchUpInside)
    cameraButton.widthAnchor.constraint(equalToConstant: 70.0).isActive = true
    calenderButton.setImage(UIImage(named: "calender"), for: .normal)
    calenderButton.addTarget(self, action: #selector(calanderTapped), for: .touchUpInside)
    calenderButton.widthAnchor.constraint(equalToConstant: 70.0).isActive = true

    stackView.frame = CGRect(x: 0, y: 0, width: scrollView.frame.size.width, height: scrollViewHeight)
    stackView.axis = .horizontal
    stackView.spacing = 5
    stackView.semanticContentAttribute = .forceLeftToRight
    stackView.alignment = .fill // .leading .firstBaseline .center .trailing .lastBaseline
    stackView.distribution = .equalSpacing // .fillEqually .fillProportionally .equalSpacing .equalCentering
    stackView.addArrangedSubview(calenderButton)
    stackView.addArrangedSubview(cameraButton)
    stackView.backgroundColor = UIColor(red: 0.161, green: 0.165, blue: 0.188, alpha: 1.00)
    scrollView.addSubview(stackView)

What is the problem: The StackView is not aligning the subviews to the left.

What I am trying to achieve:

I want all the subviews aligned to the left, I tried to do this with stackView.semanticContentAttribute = .forceLeftToRight, but that didn't seem to achieve much.

Cal
  • 422
  • 6
  • 20

3 Answers3

2

Set:

    stackView.alignment = .leading 

And remove This:

    stackView.distribution = .equalSpacing

Your code then will be like:

    cameraButton.setImage(UIImage(named: "blueCamera"), for: .normal)
    cameraButton.addTarget(self, action: #selector(cameraTapped), for: .touchUpInside)
    cameraButton.widthAnchor.constraint(equalToConstant: 70.0).isActive = true
    calenderButton.setImage(UIImage(named: "calender"), for: .normal)
    calenderButton.addTarget(self, action: #selector(calanderTapped), for: .touchUpInside)
    calenderButton.widthAnchor.constraint(equalToConstant: 70.0).isActive = true

    stackView.frame = CGRect(x: 0, y: 0, width: scrollView.frame.size.width, height: scrollViewHeight)
    stackView.axis = .horizontal
    stackView.spacing = 5
    stackView.alignment = .leading    
    stackView.addArrangedSubview(calenderButton)
    stackView.addArrangedSubview(cameraButton)
    stackView.backgroundColor = UIColor(red: 0.161, green: 0.165, blue: 0.188, alpha: 1.00)
    scrollView.addSubview(stackView)
B25Dec
  • 2,301
  • 5
  • 31
  • 54
rptwsthi
  • 10,094
  • 10
  • 68
  • 109
2

You can achieve this by using transparent UIView with dynamic width. So each image view will have width constraint except this UIView. Also set stackView.alignment and stackView..distribution properties to .fill.

Using this you can show/hide imageViews with consistent left alignment.

Here is quick setup using storyboard. As you can see all images have width set to 60 except last UIView names "Blue Dynamic Width View". enter image description here

Dima Cheverda
  • 402
  • 1
  • 4
  • 10
1

Couple options...

1) Constrain stack view Leading and Bottom, but not Trailing; Constrain width and height of first subview; Constrain additional subviews equal width and height to first subview; give stack view desired spacing.

2) Constrain stack view Leading, Trailing and Bottom; Constrain width and height of first subview; Constrain additional subviews equal width and height to first subview; give stack Distribution: Equal Spacing; add extra clear subviews to add up to 4 total subviews.

3) Same constraints as 2, but add 4 clear subviews, then add buttons as subviews of those subviews.

DonMag
  • 69,424
  • 5
  • 50
  • 86