0

I'm using Xcode 10/Swift 5/iOS 12 and got this layout:

enter image description here

The red (vertical) StackView is set to:

  • Distribution: "Fill Equally"
  • Height: 300 (fixed)
  • Frame: 10 (each side)
  • Spacing: 10

5 horizontal sub-StackViews:

  • Distribution: "Fill Equally"
  • 52 pixels tall each ((300-40)/5) - not fixed!

The blue View simply takes up the remaining screen space (top aligned to the red StackView and bottom to "SuperView").

The labels automatically take up the 52 pixels but I want the two TextFields to be exactly 30 pixels (+11 above/below). If I just set the height, InterfaceBuilder complains about a conflict and doesn't actually change anything.

How do I set their height without changing the height of the surrounding horizontal StackView?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Neph
  • 1,823
  • 2
  • 31
  • 69
  • Just set the contentHugging priority and compressionResistance priority to required in the storyboard for each text field. – Pranav Kasetti Apr 11 '19 at 15:33
  • @PranavKasetti Sorry, what do you mean with `to required`? I know where to set the "Priority" values (in the "size inspector") but I don't see any other settings for them. – Neph Apr 11 '19 at 15:42
  • Required means the highest value (1000) – Pranav Kasetti Apr 11 '19 at 15:50
  • @PranavKasetti I set both "Vertical" priorities to "1000" for the first TextField but that didn't change anything - it's still complaining about the conflict. – Neph Apr 11 '19 at 15:52
  • Try setting the alignment of the horizontal stack view to fill instead of fillEqually, and using width constraints instead – Pranav Kasetti Apr 11 '19 at 15:55
  • Do you want your labels to be 52-pts tall, regardless of device / screen height? Or, do you want your stack view to be 300-pts tall with 10-pt spacing, and the labels equal heights with the textfields vertically centered? – DonMag Apr 11 '19 at 18:08
  • @PranavKasetti "Fill" makes the "Time" StackView really big and the others really small. If there's a way to not "hardcode" it, it's prefer that one. – Neph Apr 12 '19 at 08:39
  • @DonMag Yes and no. I want the StackView to be a fixed 300 height with a spacing of 10. I don't care if the labels themselves are exactly 52 tall or if they're less than that (even though bigger would probably be better if someone changes their font size), as long as the sub-StackViews fill the red one equally. If possible, I'd prefer to not give the sub-StackViews a fixed height. – Neph Apr 12 '19 at 08:44

1 Answers1

3

Here is one solution - assuming you want each "row" in your stack view to be 52-pts tall (labels have green background, just to make their frames easier to see).

enter image description here

Red Stack View:

Alignment: Fill
Distribution: Fill Equally
Spacing: 10

Each Horizontal stack view:

Alignment: Center
Distribution: Fill Equally
Spacing: 0

Red View - which holds Red Stack View and Blue View - is constrained at Zero to SuperView on all four sides.

Red Stack View is constrained Top, Leading and Trailing to its SuperView (which is Red View) at 10-pts.

Blue View is constrained Leading, Trailing and Bottom to its SuperView (which is Red View) at 10-pts, and Top at 10-pts to Bottom of Red Stack View.

The only Height constraint is set on Date Stack View ... Height = 52. Since Red Stack View has its distribution set to Fill Equally the remaining horizontal stack views will automatically get heights of 52.

And, by setting Alignment: Center on each horizontal stack view, the arranged subviews will be center-aligned to that 52-pt height.

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • "Center" did the trick, thank you! I just left the rest the way it was - including the overall height of 300 (changing it, if necessary, is easier that way imo) and added 2 constraints to each label to align the top and bottom to its parent StackView. – Neph Apr 12 '19 at 08:56
  • Another question that's related to the layout in my question: Tinting a StackView doesn't work, it seems like you can only change the background color of normal views, labels,... If I want to give my "Date StackView" a green background color, I know that I can put the label and text field in their own view, then change their colors. But is there an easier way? – Neph Apr 12 '19 at 09:19
  • 1
    From Apple docs: *"`UIStackView` is a nonrendering subclass of `UIView`; that is, it does not provide any user interface of its own. Instead, it just manages the position and size of its arranged views."* So, the only way to do that is to embed elements in other views. – DonMag Apr 12 '19 at 12:10
  • Sorry, one more question: How do I add padding to the left of the text of the labels but still within the label? So e.g. 5pts of green, free space within your green labels and only then the text starts. Is there a better way than just adding spaces within the text? – Neph Apr 15 '19 at 11:53
  • 1
    You could use attributed text with an indented paragraph style, or... embed the label in a `UIView` with a leading constraint, or... subclass `UILabel` and override `drawTextInRect:`, or... searching for `uilabel insets` returns various other approaches. – DonMag Apr 15 '19 at 12:09
  • Ah, so you can't just use a constraint for that. Okay, thanks! – Neph Apr 15 '19 at 15:07