Search code examples
iosswiftstoryboarduistackview

How do I make UIStackView's elements center alignment


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.


Solution

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