3

What I want to achieve

How do I make the elements to the center of UIStackview under the below condition?

  • Using Storyboard

  • Axis is Horizontal

  • Alignment is Fill

  • Distribution is Fill

  • Spacing is 0

  • UIStackView have three UILabels that have different length of string

  • The leading and trailing constraint is equal to super view (same as a screen width)

enter image description here

The problem

if I add the constraint of the center horizontal to the super view and remove leading and trailing constraint, it seems to be OK but I will stick out of the screen because there is no constraint of leading and trailing.

What I tried

I have already tried to change UIStackView's Alignment、Distribution、Spacing but it didn't help. Also, I couldn't find any solution or the best practice from google.

Capotasto
  • 131
  • 3
  • 17
  • Not quite clear... Do you want the *combined* length of the 3 labels to be centered horizontally? Or do you want the bigger "HEY" centered horizontally, with "Hi, there" going further left and "Hi" not very far right? – DonMag Feb 12 '20 at 17:34
  • @DonMag I use three UILabel because one of them has a different color and font size. Then just want to know how to make this center alignment with leading and trailing constraint to the super view. Is this clear? – Capotasto Feb 13 '20 at 01:12

3 Answers3

3

As PatPatchPatrick said, you can constrain the stack view Horizontally centered.

But, You have to consider what will happen if your strings are too long.

Your example strings are:

    leftStr = "Hi, there"
    midStr = "HEY"
    rightStr = "Hi"

and, with a centered stack view you get:

enter image description here

Suppose, though, your strings are:

    // Set A
    leftStr = "Hi, there from the Left"
    midStr = "HEY MIDDLE"
    rightStr = "Hi from the Right"

or:

    // Set B
    leftStr = "Hi, there from the Left"
    midStr = "HEY"
    rightStr = "Hi"

Now you get:

enter image description here

2 - Whoops... the stack view extends outside the bounds of the view.

3 - So, we'll add '>=8leading and trailing (so we have a little padding on each side). Whoops, the text gets truncated... and which label(s) get...` will depend on Content Compression Priority settings.

4 - To avoid truncation, we'll set the labels to Number of Lines: 0 so the text will wrap. Maybe looks ok, maybe not.

5 - Let's set the labels' Text Alignment to Center. Maybe what we want?

6 - However, with "Set B" strings instead of "Set A" --- maybe not so good?

A better option may be to use a single, centered label (with >=8 leading and trailing constraints):

enter image description here

and use Attributed Text:

enter image description here

Here is how you could define and set the Attributed Text:

    let leftStr = "Hi, there"
    let midStr = "HEY"
    let rightStr = "Hi"

    let font1 = UIFont.systemFont(ofSize: 17.0)
    let font2 = UIFont.boldSystemFont(ofSize: 26.0)
    let offset = (font1.xHeight - font2.xHeight) * 0.5

    let attributedStr = NSMutableAttributedString(string: leftStr + " ", attributes: [NSAttributedString.Key.font: font1])
    attributedStr.append(NSAttributedString(string: midStr, attributes: [NSAttributedString.Key.font: font2, NSAttributedString.Key.foregroundColor: UIColor.red, NSAttributedString.Key.baselineOffset: offset]))
    attributedStr.append(NSMutableAttributedString(string: " " + rightStr, attributes: [NSAttributedString.Key.font: font1]))

    theLabel.attributedText = attributedStr

As a side note, and for your future reference...

It helps to fully define your question. Presumably, in your actual app, you won't be displaying:

"Hi, there HEY Hi"

so it's entirely possible that none of these approaches will give you the results you want.

It would have been much better if you had included real examples of what your app will be displaying, and how you want it to look.

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • Yeah, that's what I'm concerned about after reading _PatPatchPatrick_ answer. I think the best way, for my case, is using one UILabel and Attributed Text. Thanks. – Capotasto Feb 14 '20 at 05:00
2

You mean like this?

Set "alignment = Fill", distribution = "equal spacing". And make sure all of your labels Layout is set to "automatic" and not "Translate mask into constraints".

If you need a light blue background behind stackview like in your image above, just set the stackview to be inside of a UIView. I don't think you can stretch a stackview out that far and also have the contents inside of it centered.

Make the leading and trailing constraint >= 0, so if the stackview gets too big, it will still be constrained.

enter image description here

PatPatchPatrick
  • 380
  • 1
  • 12
2

You can add two spacer view in your stack those will cover the remaining space

working example

enter image description here

Jawad Ali
  • 13,556
  • 3
  • 32
  • 49
  • What is the leading and trailing space to the super view of your UIStackView? I tried adding two spacers (width = 16) but if the screen size is big, like iPhone 11 max, the UILabel expands. – Capotasto Feb 12 '20 at 09:01
  • dont fix the width of (spacer) views ... they automatically take remaining space – Jawad Ali Feb 12 '20 at 09:08