Center UIStackView not centering view - swift

I have this
view.addSubview(myName)
myName.topAnchor.constraint(equalTo: myImage.bottomAnchor).isActive = true
myName.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
myName.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
let stackView = UIStackView(arrangedSubviews: [myValue1,myValue2])
view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.alignment = .center
stackView.topAnchor.constraint(equalTo: myName.bottomAnchor).isActive = true
Any idea why it looks like this? I want it to be centered vertically like Example Text, I've tried adding
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
but then it looks like this
Any idea what I'm missing?

Try
stackView.centerXAnchor.constraint(equalTo: myName.centerXAnchor).isActive = true
This should center the stack view itself against the myName label
note that if you want stuff in stack view to align nicely you have to give it some proportional or fixed widths, and give your stackview a width.
Update
if you want space between labels, add an extra UIView() between them into the stack:
let spacer = UIView()
spacer.widthAnchor.constraint(equalToConstant: 40.0).isActive = true
let stackView = UIStackView(arrangedSubviews: [myValue1,spacer, myValue2])

Related

How to set specific width to stackview child, swift?

I'm creating a stackview, inside which there are 5 sub views. (3 custom views divided by 2 separator views). Two separator views's width must be 1 and every sub views must be center and fill equally.
Here's my current code and result which doesn't look nice.
var stackView: UIStackView = {
let view = UIStackView()
view.axis = .horizontal
view.alignment = .center
view.distribution = .fillEqually
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
func setUpView() {
containerView.addSubview(stackView)
stackView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 8).isActive = true
stackView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -8).isActive = true
stackView.leadingAnchor.constraint(equalTo: homeLogoImageView.trailingAnchor , constant: 18).isActive = true
stackView.trailingAnchor.constraint(equalTo: awayLogoImageView.leadingAnchor, constant: -18).isActive = true
stackView.addArrangedSubview(homeWinView)
stackView.addArrangedSubview(seperator1)
stackView.addArrangedSubview(drawView)
stackView.addArrangedSubview(seperator2)
stackView.addArrangedSubview(awayWinView)
seperator1.widthAnchor.constraint(equalToConstant: 1).isActive = true
seperator1.heightAnchor.constraint(equalToConstant: 60).isActive = true
seperator2.widthAnchor.constraint(equalToConstant: 1).isActive = true
seperator2.heightAnchor.constraint(equalToConstant: 60).isActive = true
}
Output:
Expectation:
fillEqually doesn't work, when you just want some of your views in your stack view to fill equally.
Change fillEqually to fill, and add the "equally" part using constraints yourself.
NSLayoutConstraint.activate([
homeWinView.widthAnchor.constraint(equalTo: drawView.widthAnchor),
homeWinView.widthAnchor.constraint(equalTo: awayWinView.widthAnchor),
])

constraint object by percentage in a stackview

I want to create a constraint that is 80 percent of the width of the uiview controller not a 100 percent which is what it is now. I tried using the var percent but its not working. The code should be centered on the y axis. So 10 percent on the left side and ride side are not covered by the constraint. I am trying to do this in a stack view.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//Image View
let percent = ((UIScreen.main.bounds.midY) + (UIScreen.main.bounds.maxX * 0.8))
//Text Label
let textLabel = UILabel()
textLabel.backgroundColor = UIColor.yellow
textLabel.widthAnchor.constraint(equalToConstant: self.view.frame.width * percent).isActive = true
textLabel.heightAnchor.constraint(equalToConstant: 20.0).isActive = true
textLabel.text = "Hi World"
textLabel.textAlignment = .center
//Stack View
let stackView = UIStackView()
stackView.axis = NSLayoutConstraint.Axis.vertical
stackView.distribution = UIStackView.Distribution.equalSpacing
stackView.alignment = UIStackView.Alignment.center
stackView.spacing = 16.0
stackView.addArrangedSubview(textLabel)
stackView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(stackView)
//Constraints
stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
}
}
Set the widthAnchor of stackView with that of superView's width (in this case view controller's view) and set multiplier value as 0.80
stackView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.80).isActive = true
You can achieve this by setting 'widthAnchor' and 'centerXAnchor' like below. We need to always keep horizontal center of child view and super view same. Whereas width of child should be 80 percentage(here 0.8 indicates 80%) of super view.
stackView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.8, constant: 0).isActive = true
stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true

UIStackView - why is the stack positioned one on top of the other?

I am trying to get a group of buttons arranged within a stack view. However, when i use a for-each loop to do this, the buttons end up being positioned one on top of the other?
var stackView: UIStackView = {
let sView = UIStackView()
sView.axis = .vertical
sView.distribution = .fill
sView.alignment = .center
return sView
}()
var optionTitles = ["Sign in", "sign out"]
for title in optionTitles{
let btn = UIButton()
btn.setTitle(title, for: .normal)
btn.backgroundColor = optionColour.withAlphaComponent(0.6)
allButtons.append(btn)
stackView.addSubview(btn)
}
// Auto layout constraints
for button in allButtons{
button.translatesAutoresizingMaskIntoConstraints = false
button.heightAnchor.constraint(equalToConstant: optionHeight).isActive = true
button.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true
}
view.addSubview(stackView)
stackTopConstraint = stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
stackBottomConstraint = stackView.bottomAnchor.constraint(equalTo: view.topAnchor)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
stackTopConstraint!.isActive = true
stackView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
2 things
1- You need to remove this
button.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true
2- Replace
stackView.addSubview(btn)
with
stackView.addArrangedSubview(btn)
You have:
stackTopConstraint = stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor)
stackBottomConstraint = stackView.bottomAnchor.constraint(equalTo: view.topAnchor)
You probably meant view.bottomAnchor in the second line. Surely you don't want to constraint the bottom of the stack view to the top of your view.

Swift: Unable to clip image in stackView

I am attempting to layout an imageView inside a stackView and was unable to clip the image. The layout was correctly done when no image was inserted as shown:
However, when I insert a dummy image (a portrait image) to test the contentMode and clipsToBounds, it stretched, like so:
I have read this post and also tried to layout the imageView inside a UIView before stacking inside the stackView but it still gave the same result. Note that I would want my two labels to adopt its intrinsicContentSize as the titleLabel may take up 1 or 2 lines. I would want the imageView to adjust accordingly.
My implementation:
let drawingPreviewImageView: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.image = UIImage(named: "testImage")
iv.backgroundColor = .lightGray
iv.contentMode = .scaleAspectFill
iv.clipsToBounds = true
iv.layer.masksToBounds = true
return iv
}()
let stackView = UIStackView(arrangedSubviews: [
drawingPreviewImageView,
numberLabel,
titleLabel,
])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.spacing = 4
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4 )
addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: topAnchor),
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
stackView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
Any advice?

Swift UIStackView: Positioning elements from center programmatically

I am trying to get elements inside a UIStackView to position themselves equally from the center.
This is the desired effect I would like:
As you can see, I would like the two text fields to be equally spaced from each other and aligned center within the stack view.
This stack view will have either 1 - 7 textfields that I need lined up.
Here is what is currently coming out:
This is how I am setting the Text Fields
let textLabel = UILabel()
textLabel.backgroundColor = UIColor.red
textLabel.widthAnchor.constraint(equalToConstant: 40.0).isActive = true
textLabel.heightAnchor.constraint(equalToConstant: 20.0).isActive = true
textLabel.text = "Hi"
textLabel.textAlignment = .center
let textLabel1 = UILabel()
textLabel1.backgroundColor = UIColor.red
textLabel1.widthAnchor.constraint(equalToConstant: 40.0).isActive = true
textLabel1.heightAnchor.constraint(equalToConstant: 20.0).isActive = true
textLabel1.text = "Hi"
textLabel1.textAlignment = .center
I am generating the stack view like so:
//Stack View
let stackView = UIStackView()
stackView.axis = UILayoutConstraintAxis.horizontal
stackView.distribution = UIStackViewDistribution.equalCentering
stackView.alignment = UIStackViewAlignment.fill
stackView.spacing = 16.0
stackView.addArrangedSubview(textLabel)
stackView.addArrangedSubview(textLabel1)
stackView.translatesAutoresizingMaskIntoConstraints = false;
self.view.addSubview(stackView)
//Constraints
stackView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 50).isActive = true
stackView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -50).isActive = true
stackView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100).isActive = true
How do I get the elements inside to align center?
I thought it was
UIStackViewDistribution.equalCentering
However, that didn't do much.
Thats odd. Normally a horizontal UIStackView with center alignment and equal centering distribution should do exactly that:
But maybe I'm not understanding you correct and you actually want something like this:
In which case you have to chose Fill Equally as the distribution method and make the labels itself center their text: