Add UILabel over UIImage inside StackView - ios

The part of my storyboard looks like on first photo. On second photo I present constraints. What I am trying to achieve is to put UILabel at the bottom over the UIImageView (with photo "DJI_0049").

Add the label to the same view as the UIStackView.. such that they are siblings/adjacent views. Add the imageView to the stackView and then constrain the label to the imageView.
Since they are siblings it WILL work. Do note that the label CANNOT be an arranged sub-view of the stackView.. otherwise broken constraints will be the result.
Example:
//
// ViewController.swift
// TestSO
//
// Created by Brandon on 2018-02-28.
// Copyright © 2018 XIO. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel()
let imageView = UIImageView()
let otherView = UIView()
let otherView2 = UIView()
let stackView = UIStackView()
stackView.axis = .vertical
stackView.alignment = .fill
stackView.distribution = .fill
self.view.addSubview(stackView)
self.view.addSubview(label)
stackView.addArrangedSubview(imageView)
stackView.addArrangedSubview(otherView)
stackView.addArrangedSubview(otherView2)
label.text = "Hello World"
label.textColor = UIColor.white
imageView.backgroundColor = UIColor.purple
otherView.backgroundColor = UIColor.red
otherView2.backgroundColor = UIColor.blue
stackView.translatesAutoresizingMaskIntoConstraints = false
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor),
stackView.rightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.rightAnchor),
stackView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
stackView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor)
])
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: imageView.centerXAnchor),
label.centerYAnchor.constraint(equalTo: imageView.centerYAnchor),
label.leftAnchor.constraint(greaterThanOrEqualTo: imageView.leftAnchor),
label.rightAnchor.constraint(lessThanOrEqualTo: imageView.rightAnchor),
label.topAnchor.constraint(greaterThanOrEqualTo: imageView.topAnchor),
label.bottomAnchor.constraint(lessThanOrEqualTo: imageView.bottomAnchor)
])
NSLayoutConstraint.activate([
imageView.heightAnchor.constraint(equalToConstant: 100.0),
otherView.heightAnchor.constraint(equalToConstant: 100.0),
otherView2.heightAnchor.constraint(equalToConstant: 100.0)
])
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

You can’t overlap views like this in a stack view.
Your best option is to use normal auto layout constraints to lay out one of the views (probably the image) and then either use a stack view or constraints to layout the views that you want over it.

With a UIStackView this will not work (for as far I know UIStackView?!). But it can be easily achieved with the following constraints:
Set leading, top and trailing edges from the UIImageView to his superview. Define some height for the UIImageView.
Secondly, set leading and trailing edges from the UILabel to the UIImageView. Make sure the UILabel and UIImageView share the same superview.
Lastly, set the bottom of the UILabel to the bottom of the UIImageView.

i was also able to do this in a stackview by adding the label as a subview to the image view.
cell.avatarImage.leadingAnchor.constraint(equalTo: cell.cellBodyStackView.leadingAnchor, constant: 10).isActive = true
cell.avatarImage.topAnchor.constraint(equalTo: cell.cellBodyStackView.topAnchor).isActive = true
cell.avatarImage.bottomAnchor.constraint(equalTo: cell.cellBodyStackView.bottomAnchor).isActive = true
cell.avatarImage.trailingAnchor.constraint(equalTo: cell.commentLabel.leadingAnchor, constant: -10).isActive = true
cell.avatarImage.widthAnchor.constraint(lessThanOrEqualToConstant: cellWidth * 0.25).isActive = true
cell.avatarImage.addSubview(cell.usernameLabel)
cell.usernameLabel.trailingAnchor.constraint(equalTo: cell.avatarImage.trailingAnchor).isActive = true
cell.usernameLabel.leadingAnchor.constraint(equalTo: cell.avatarImage.leadingAnchor).isActive = true
cell.usernameLabel.bottomAnchor.constraint(equalTo: cell.avatarImage.bottomAnchor).isActive = true
cell.usernameLabel.centerXAnchor.constraint(equalTo: cell.avatarImage.centerXAnchor).isActive = true
cell.usernameLabel.textAlignment = .center
cell.usernameLabel.backgroundColor = UIColor.black.withAlphaComponent(0.5)
cell.usernameLabel.textColor = UIColor.white

Related

(Swift 5) UIScrollView scrolls but none of the content scrolls (video included)

I'm trying to learn to build views without storyboard. I tried to build a scrollview. On that scrollview is a UISearchBar, a UIImageView with an image and a UILabel. It works but none of the content moves. The content is all just frozen in place like no matter how far I scroll the search bar will always be on top of the page. and the image on the bottom. I've attached a video to show what I mean. There's also a problem because none of the content is where I want it to be but that's another problem. I realize this is probably because I don't know enough about constraints and autolayout and building views without storyboards.
Here's the video
class HomePageViewController: UIViewController {
var searchedText: String = ""
let label = UILabel()
let searchBar: UISearchBar = {
let searchBar = UISearchBar()
searchBar.placeholder = "Where are you going?"
searchBar.translatesAutoresizingMaskIntoConstraints = false
searchBar.barTintColor = .systemCyan
searchBar.searchTextField.backgroundColor = .white
searchBar.layer.cornerRadius = 5
return searchBar
}()
let homeImage: UIImageView = {
let homeImage = UIImageView()
homeImage.translatesAutoresizingMaskIntoConstraints = false
homeImage.clipsToBounds = true
return homeImage
}()
let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.backgroundColor = .systemMint
scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 30)
return scrollView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemPink
// setupLayout()
// tried this here doesn't do anything for me
}
func setupLayout() {
view.addSubview(scrollView)
self.scrollView.addSubview(searchBar)
homeImage.image = UIImage(named: "Treehouse")
self.scrollView.addSubview(homeImage)
label.text = "Inspiration for your next trip..."
self.scrollView.addSubview(label)
// not sure where this label is being added I want it to be underneath the image but it isn't t
let safeG = view.safeAreaLayoutGuide
let viewFrame = view.bounds
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: -10),
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor),
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
searchBar.topAnchor.constraint(equalTo: safeG.topAnchor, constant: 50.0),
searchBar.widthAnchor.constraint(equalTo: safeG.widthAnchor, multiplier: 0.9),
searchBar.centerXAnchor.constraint(equalTo: safeG.centerXAnchor),
homeImage.topAnchor.constraint(equalTo: safeG.topAnchor, constant: 150),
homeImage.widthAnchor.constraint(equalTo: safeG.widthAnchor, multiplier: 1.1),
homeImage.centerXAnchor.constraint(equalTo: safeG.centerXAnchor),
homeImage.heightAnchor.constraint(equalToConstant: viewFrame.height/2),
label.topAnchor.constraint(equalTo: homeImage.bottomAnchor, constant: 100)
])
// was doing all this in viewDidLayoutSubviews but not sure if this is better place for it
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
setupLayout()
// tried this in viewDidLoad() and it didn't solve it.
}
}
any help would be appreciated
First, when constraining subviews in a UIScrollView, you should constrain them to the scroll view's Content Layout Guide. You're constraining them to the view's safe area layout guide, so they're never going to go anywhere.
Second, it's difficult to center subviews in a scroll view, because the scroll view can scroll both horizontally and vertically. So it doesn't really have a "center."
You can either put subviews in a stack view, or, quite common, use a UIView as a "content" view to hold the subviews. If you constrain that content view's Width to the scroll view's Frame Layout Guide width, you can then horizontally center the subviews.
Third, it can be very helpful to comment your constraints, so you know exactly what you expect them to do.
Here's a modified version of your posted code:
class HomePageViewController: UIViewController {
var searchedText: String = ""
let label: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
let searchBar: UISearchBar = {
let searchBar = UISearchBar()
searchBar.placeholder = "Where are you going?"
searchBar.translatesAutoresizingMaskIntoConstraints = false
searchBar.barTintColor = .systemCyan
searchBar.searchTextField.backgroundColor = .white
searchBar.layer.cornerRadius = 5
return searchBar
}()
let homeImage: UIImageView = {
let homeImage = UIImageView()
homeImage.translatesAutoresizingMaskIntoConstraints = false
homeImage.clipsToBounds = true
return homeImage
}()
let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.backgroundColor = .systemMint
// don't do this
//scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 30)
return scrollView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemPink
setupLayout()
}
func setupLayout() {
view.addSubview(scrollView)
//homeImage.image = UIImage(named: "Treehouse")
homeImage.image = UIImage(named: "natureBKG")
label.text = "Inspiration for your next trip..."
// let's use a UIView to hold the "scroll content"
let contentView = UIView()
contentView.translatesAutoresizingMaskIntoConstraints = false
// give it a green background so we can see it
contentView.backgroundColor = .green
contentView.addSubview(searchBar)
contentView.addSubview(homeImage)
contentView.addSubview(label)
scrollView.addSubview(contentView)
let safeG = view.safeAreaLayoutGuide
let svContentG = scrollView.contentLayoutGuide
let svFrameG = scrollView.frameLayoutGuide
NSLayoutConstraint.activate([
// constrain scrollView to all 4 sides of view
// (generally, constrain to safe-area, but this is what you had)
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor),
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
// constrain contentView to all 4 sides of scroll view's Content Layout Guide
contentView.topAnchor.constraint(equalTo: svContentG.topAnchor, constant: 0.0),
contentView.leadingAnchor.constraint(equalTo: svContentG.leadingAnchor, constant: 0.0),
contentView.trailingAnchor.constraint(equalTo: svContentG.trailingAnchor, constant: 0.0),
contentView.bottomAnchor.constraint(equalTo: svContentG.bottomAnchor, constant: 0.0),
// constrain contentView Width equal to scroll view's Frame Layout Guide Width
contentView.widthAnchor.constraint(equalTo: svFrameG.widthAnchor),
// constrain searchBar Top to contentView Top + 50
searchBar.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 50.0),
// constrain searchBar Width to 90% of contentView Width
searchBar.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.9),
// constrain searchBar centerX to contentView centerX
searchBar.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
// constrain homeImage Top to searchBar Bottom + 40
homeImage.topAnchor.constraint(equalTo: searchBar.bottomAnchor, constant: 40.0),
// constrain homeImage Width equal to contentView Width
homeImage.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 1.0),
// constrain homeImage centerX to contentView centerX
homeImage.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
// constrain homeImage Height to 1/2 of scroll view frame Height
homeImage.heightAnchor.constraint(equalTo: svFrameG.heightAnchor, multiplier: 0.5),
// you probably won't get vertical scrolling yet, so increase the vertical space
// between the homeImage and the label by changing the constant
// from 100 to maybe 400
// constrain label Top to homeImage Bottom + 100
label.topAnchor.constraint(equalTo: homeImage.bottomAnchor, constant: 100.0),
// constrain label centerX to contentView centerX
label.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
// constrain label Bottom to contentView Bottom - 20
label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20.0),
])
}
}

UIImageView ignores widthAnchor inside UIStackView

I'm trying to align and scale an image inside a UIStackView:
class LogoLine: UIViewController {
override func viewDidLoad() {
let label = UILabel()
label.text = "powered by"
label.textColor = .label
label.textAlignment = .center
let logoToUse = UIImage(named: "Image")
let imageView = UIImageView(image: logoToUse!)
let stackView = UIStackView(arrangedSubviews: [label, imageView])
stackView.axis = .vertical
stackView.distribution = .fillProportionally
view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.widthAnchor.constraint(equalToConstant: 50), // this gets ignored
stackView.topAnchor.constraint(equalTo: self.view.topAnchor),
stackView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
view.heightAnchor.constraint(equalTo: stackView.heightAnchor)
])
}
}
This is how it looks in the simulator (going from border to border):
Question: Why is the UIImageView ignoring my widthAnchor constraint of 50pt, and why does the aspect ratio of the original image get changed? How can I constrain the UIImage (or the UIImageView) to e.g. half the screen width and maintain the aspect ratio?
By default, a vertical stack view has .alignment = .fill ... so it will stretch the arranged subviews to "fill the width of the stack view."
Change it to:
stackView.alignment = .center
As a side note, get rid of the stackView.distribution = .fillProportionally ... it almost certainly is not what you want.

Can't get StackView to view items properly

I'm trying to add 4 items to a UIStackView, this 4 Items are all a simple square UIView, I added them all to a UIStackView but they won't stay square, it's like the UIStackView squeezes them or something. I tried setting the UIStackView to be the same height of the items, and set it's width to be the height of the items * 4 so I can try and get 1:1 ratio, but nothing worked for me.
The UIView is a simple UIView with background color. I tried to set it's widthAnchor and heightAnchor to 50, but I know the UIStackView has it's own way to size the items in it.
I don't really know what to do about this.
This is my UIStackView setup and constraints:
Setup:
private lazy var optionButtonStack: UIStackView = {
let stack = UIStackView(arrangedSubviews: [self.optionButton1, self.optionButton2, self.optionButton3, self.optionButton4])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.distribution = .fillEqually
stack.axis = .horizontal
stack.spacing = 2.5
return stack
}()
Constraints:
private func setupOptionButtonStack() {
addSubview(optionButtonStack)
NSLayoutConstraint.activate([
optionButtonStack.heightAnchor.constraint(equalToConstant: 50),
optionButtonStack.widthAnchor.constraint(equalToConstant: 200),
optionButtonStack.centerXAnchor.constraint(equalTo: self.centerXAnchor),
optionButtonStack.bottomAnchor.constraint(equalTo: buyNowButton.topAnchor, constant: -8),
])
}
This is the UIView in case this is needed:
private let optionButton1: UIView = {
let view = UIView()
view.backgroundColor = .appBlue
view.translatesAutoresizingMaskIntoConstraints = false
view.widthAnchor.constraint(equalToConstant: 50).isActive = true
view.heightAnchor.constraint(equalToConstant: 50).isActive = true
view.tag = 1
return view
}()
Give the button view a single constraint setting its width equal to its height:
view.widthAnchor.constraint(equalTo: view.heightAnchor).isActive = true
and set the stack view alignment at center.

How to add fixed size UIView to UIStackView?

On the latest Xcode (10.1), I'm having trouble adding a fixed size UIView to my UIStackView using programmatic constraints. I think this should be straightforward, but I don't understand where extra constraints are coming from (that UIKit has to break some to layout the views).
The problem is that I am expecting a blue UIView of 100x100. The reality is that the blue UIView is 100% screen width & 100% screen height.
I realize UIStackView uses intrinsicContentSize, but how do I set that correctly using programmatic constraints?
The following is a working playground with an UIStackView & a vanilla UIView added.
Note: if I add the blue UIView directly to the ViewController's view, the size is correct at 100x100 at origin (0,0). Adding it to the stack view causes constraint conflicts.
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
self.view = view
// vertical stack view (full screen)
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: view.topAnchor),
stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stackView.widthAnchor.constraint(equalTo: view.widthAnchor),
])
// view (100x100)
let fixedSizeView = UIView()
fixedSizeView.translatesAutoresizingMaskIntoConstraints = false
fixedSizeView.backgroundColor = .blue
stackView.addArrangedSubview(fixedSizeView)
NSLayoutConstraint.activate([
fixedSizeView.widthAnchor.constraint(equalToConstant: 100),
fixedSizeView.heightAnchor.constraint(equalToConstant: 100),
])
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
The main purpose of a UIStackView is to arrange its subviews.
So, you are constraining your stack view to "fill the screen" and then adding your "blue view" as an arranged subview ... at which point the stack view will "take over" the arrangement of the blue view.
Assuming you are using a stack view because you are planning on adding additional views, you can either allow the subviews to determine the stack view's frame (that is, don't constrain your stack view's width and/or height), or you need to change the stack view's .alignment and/or .distribution properties.
Here is a modification of your playground page to put the 100 x 100 blue view centered in the superview:
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
self.view = view
// vertical stack view (full screen)
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
view.addSubview(stackView)
// NSLayoutConstraint.activate([
// stackView.topAnchor.constraint(equalTo: view.topAnchor),
// stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
// stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
// stackView.widthAnchor.constraint(equalTo: view.widthAnchor),
// ])
NSLayoutConstraint.activate([
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
// view (100x100)
let fixedSizeView = UIView()
fixedSizeView.translatesAutoresizingMaskIntoConstraints = false
fixedSizeView.backgroundColor = .blue
stackView.addArrangedSubview(fixedSizeView)
NSLayoutConstraint.activate([
fixedSizeView.widthAnchor.constraint(equalToConstant: 100),
fixedSizeView.heightAnchor.constraint(equalToConstant: 100),
])
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
and, here's a modification where two views - blue and red, each at 100 x 100 - get added to a stack view that is constrained to the top of the superview, with .alignment set to .center:
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
self.view = view
// vertical stack view (full screen)
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stackView.topAnchor.constraint(equalTo: view.topAnchor),
])
// view (100x100)
let fixedSizeBlueView = UIView()
fixedSizeBlueView.translatesAutoresizingMaskIntoConstraints = false
fixedSizeBlueView.backgroundColor = .blue
stackView.addArrangedSubview(fixedSizeBlueView)
NSLayoutConstraint.activate([
fixedSizeBlueView.widthAnchor.constraint(equalToConstant: 100),
fixedSizeBlueView.heightAnchor.constraint(equalToConstant: 100),
])
// view (100x100)
let fixedSizeRedView = UIView()
fixedSizeRedView.translatesAutoresizingMaskIntoConstraints = false
fixedSizeRedView.backgroundColor = .red
stackView.addArrangedSubview(fixedSizeRedView)
NSLayoutConstraint.activate([
fixedSizeRedView.widthAnchor.constraint(equalToConstant: 100),
fixedSizeRedView.heightAnchor.constraint(equalToConstant: 100),
])
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

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
}
}
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.

Resources