1

I am trying to achieve a layout like this:

enter image description here

Essentially, I need the or label to stay in the middle and occupy a fixed width and the lines to stretch out towards the edges of the screen.

Here's what I did in the XIB:

  • created a horizontal UIStackview, with center alignment.
  • Set the height constraint of the stackview to 20, distribution to fill.
  • added two UIView elements(for the gray lines), with a height constraint set to 5.
  • Added a UILabel between the two UIView elements above.
  • Added more constraints:
  • left UIView leads with 0 from superview and trails with 5 to middle label
  • right UIView leads with 4 from middle label and trails with 0 to superview.

Looks fine on the Interface builder, but on different screen sizes and landscapes, I find the middle "or" label to stretch and kick away the left and right UIViews to make up for the available space, which seems right: enter image description here

If I set a width constraint of 20 on the middle label, the right UIView stretches unevenly like this:

enter image description here

I know the CHP of the elements matters to some extent here, I have even tried setting CHPs like this:

  • CHP of the middle label is 251

  • CHP of left and right UIViews is 250.

This still leaves me with the uneven stretching of right UIView.

What is it that I am doing wrong? Insights much appreciated! Thanks a lot!

Sasanka Panguluri
  • 3,058
  • 4
  • 32
  • 54

2 Answers2

3

You need to set widthConstraint on UIStackView and the make leftView.widthAnchor = rightView.widthAnchor. Alternatively you can set leading and trailing constraints on UIStackView and then set leftView.widthAnchor = rightView.widthAnchor.

Below is the sample code you can try out in Playgrounds

    let leftView = UIView()
    leftView.translatesAutoresizingMaskIntoConstraints = false
    leftView.backgroundColor = .lightGray

    let rightView = UIView()
    rightView.translatesAutoresizingMaskIntoConstraints = false
    rightView.backgroundColor = .lightGray

    let orLabel = UILabel()
    orLabel.translatesAutoresizingMaskIntoConstraints = false
    orLabel.textColor = .black
    orLabel.text = "or"

    let stackView = UIStackView(arrangedSubviews: [leftView, orLabel,  rightView])
    stackView.alignment = .center
    stackView.distribution = .fill
    stackView.axis = .horizontal
    stackView.spacing = 5
    stackView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(stackView)

    stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    stackView.heightAnchor.constraint(equalToConstant: 20).isActive = true
    stackView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true

    leftView.heightAnchor.constraint(equalToConstant: 5).isActive = true
    rightView.heightAnchor.constraint(equalToConstant: 5).isActive = true
    leftView.widthAnchor.constraint(equalTo: rightView.widthAnchor).isActive = true
Suhit Patil
  • 11,748
  • 3
  • 50
  • 60
2

Don't set any leading or trailing constraints...

Set "right view" width constraint equal to "left view" width, and give your stack view a spacing value of 4 or 5.

Storyboard:

enter image description here

Portrait:

enter image description here

Landscape:

enter image description here

DonMag
  • 69,424
  • 5
  • 50
  • 86