6

I am very new to swift and IOS and I want to place two labels side by side horizontally center programmatically. Below is my code

let secondLabel : UILabel = {
    let label = UILabel()
    label.text = "1234"
    label.textAlignment = .center
    label.translatesAutoresizingMaskIntoConstraints = false
    label.backgroundColor = UIColor.blue
    return label
}()

let thirdLabel : UILabel = {
    let label = UILabel()
    label.text = "5678"
    label.textAlignment = .center
    label.translatesAutoresizingMaskIntoConstraints = false
    label.backgroundColor = UIColor.red
    return label
}()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    setupLayout()
}

private func setupLayout(){
    view.addSubview(secondLabel)
    //secondLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    secondLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    secondLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
    secondLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true

    view.addSubview(thirdLabel)
    //thirdLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    thirdLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    thirdLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
    thirdLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true

    self.view.addConstraint(NSLayoutConstraint(
        item: thirdLabel,
        attribute: .left,
        relatedBy: .equal,
        toItem: secondLabel,
        attribute: .right,
        multiplier: 1.0,
        constant: 10
        ))
}

But this is how it looks now

enter image description here

Please help me to move the labels to the center

Appu
  • 185
  • 1
  • 3
  • 6

5 Answers5

8

You can use UIStackView to solve your problem. Please update the following code in your setupLayout method.

 private func setupLayout(){
        let stackview = UIStackView()
        stackview.axis = .horizontal
        stackview.spacing = 10
        stackview.translatesAutoresizingMaskIntoConstraints = false
        stackview.addArrangedSubview(secondLabel)
        secondLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
        secondLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true

        stackview.addArrangedSubview(thirdLabel)
        thirdLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
        thirdLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true

        self.view.addSubview(stackview)
        stackview.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        stackview.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    }

Output:- enter image description here

Manikandan
  • 1,195
  • 8
  • 26
  • How do I add flexible spacing b/w two stackview i.e. stackview.spacing = 10. Here I want flexible value instead of numeric 10 value. – Jayprakash Dubey Mar 25 '21 at 11:06
2

Well UIStackView will be the best option and @manikandan has answered properly.

But if you are not a big fan of UIStackView, you can achieve it using UIView too. A bit more lines of code and it will work.

private func setupLayout() {

    let sampleBackgroundView = UIView()

    sampleBackgroundView.translatesAutoresizingMaskIntoConstraints = false

    sampleBackgroundView.addSubview(secondLabel)
    secondLabel.topAnchor.constraint(equalTo: secondLabel.superview!.topAnchor).isActive = true
    secondLabel.bottomAnchor.constraint(equalTo: secondLabel.superview!.bottomAnchor).isActive = true
    secondLabel.leadingAnchor.constraint(equalTo: secondLabel.superview!.leadingAnchor, constant: 10).isActive = true
    secondLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
    secondLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true

    sampleBackgroundView.addSubview(thirdLabel)

    thirdLabel.topAnchor.constraint(equalTo: secondLabel.superview!.topAnchor).isActive = true
    thirdLabel.bottomAnchor.constraint(equalTo: secondLabel.superview!.bottomAnchor).isActive = true
    thirdLabel.trailingAnchor.constraint(equalTo: secondLabel.superview!.trailingAnchor, constant: 10).isActive = true
    thirdLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
    thirdLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true

    sampleBackgroundView.addConstraint(NSLayoutConstraint(
        item: thirdLabel,
        attribute: .left,
        relatedBy: .equal,
        toItem: secondLabel,
        attribute: .right,
        multiplier: 1.0,
        constant: 10
        ))

    view.addSubview(sampleBackgroundView)
    sampleBackgroundView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    sampleBackgroundView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}

Please go through these solutions and you will have a better idea to implement constraints programmatically:

Amit
  • 4,837
  • 5
  • 31
  • 46
1

While a UIStackView is one way to go (and easier many times), there are also times that you want to do what you are trying. Truth is, you're almost there.

private func setupLayout(){
    view.addSubview(secondLabel)
    secondLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: -55).isActive = true
    secondLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    secondLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
    secondLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true

    view.addSubview(thirdLabel)
    thirdLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 55).isActive = true
    thirdLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    thirdLabel.widthAnchor.constraint(equalToConstant: 100).isActive = true
    thirdLabel.heightAnchor.constraint(equalToConstant: 100).isActive = true

}

Basically, it looks like you have two 100x100 UILabels that you want 10 points apart. So:

  1. Get rid of that last constraint.
  2. Comment back in those two centerXAnchor constraints. This will move both labels on top of each other, centered horizontally.
  3. Now you just need to add a constant property to each constraint. A negative value move to the left and a positive value moves to the right. Since your widths are 100, a value of 50should make the labels be right next to each. For 10 points in between them, make it 55.
1

There're two options for you to work on that (or maybe more).

  1. Create Additional containerView(UIView) to addSubView your 2 labels. Then centerYAnchor that containerView to your baseView.
  2. Using UIStackView. Add those 2 labels into your Horizontal StackView and centerYAnchor to your baseView

Simple explanation hopes this helps.

Ly Boung
  • 185
  • 9
1

Using a container view (either UIView, or UIStackView) might be the best approach, as it would allow you to easier build other UI components around the group of two labels. But if you don't need this flexibility, or want to avoid using an extra view, you can achieve the desired layout quite nicely via layout anchors:

NSLayoutConstraint.activate([
    // set the size
    secondLabel.widthAnchor.constraint(equalToConstant: 100),
    secondLabel.heightAnchor.constraint(equalToConstant: 100),

    // center vertically in the parent view
    secondLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),

    // align to the left of the parent view center
    secondLabel.rightAnchor.constraint(equalTo: view.centerXAnchor, constant: -5),

    // set the size
    thirdLabel.widthAnchor.constraint(equalToConstant: 100),
    thirdLabel.heightAnchor.constraint(equalToConstant: 100),

    // center vertically in the parent view
    thirdLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),

    // align to the right of the parent view center
    thirdLabel.leftAnchor.constraint(equalTo: view.centerXAnchor, constant: 5)
])

The spacing between the two is automatically achieved via the offsets from the X center.

As a general note, Apple recommends activating constraints in batches, by using activate(), for performance reasons:

The effect of this method is the same as setting the isActive property of each constraint to true. Typically, using this method is more efficient than activating each constraint individually.

Cristik
  • 30,989
  • 25
  • 91
  • 127