Search code examples
iosswiftuiviewautolayoutstoryboard

Design UIView so that it can dynamically change its height based on the content height


In a XIB file I have a CustomView related to a class with the same name.

The view content is quite simple.

There are a vertical stackview and inside the stackview there are two labels. The stackview is vertically aligned to the view that contains it:

enter image description here

The first label (title) contains a static text (always a few characters). The second label (subtitle) can have variable length text.

enter image description here

I add this CustomView with other similar views as a subview of a Content View, as it was a “row”.

for i in 0...aViews.count {

   var v = CustomView(frame: CGRect(x: 0, y: _y, width: 320, height: 100))
   v.labelText = "my long label text ..."
   contentView.addSubview(v)
   // ...
}

As you can imagine, the title label should have a fixed position (top and left), that is, there cannot be a row with the title starting at 10 points and another at 14.

enter image description here

I must admit I naively thought the position of the label would have been automatically managed by the same fact that I aligned vertically the stackview. I was wrong and I noticed no problem at all, until they told me the second label, the subtitle, could contain more than one line.

I added lines to the label directly in the storyboard, and found out that:

  1. the container of the stackview doesn’t change its height based on the height of its content;

  2. the position of the “fixed” elements is maybe vertically centered but not fixed;

enter image description here

What I need is the following:

  • the labels should be “grouped” and aligned vertically: there should be the same amount of space from the top of the first label to the upper border of the container and from the bottom of the second label to the bottom border;
  • when the second label has to display more than one line, the container view should change its height accordingly;

Is this possible? How should I design my view?


Solution

  • OK - looking at your project, you're not far off... just a couple key items.

    1. In your CustomView.xib, you had no constraint between Fixed Label and Date Label. The result is that the Date Label grows up from the bottom of the view, with nothing to stop it.

    2. Also in your CustomView.xib, you had the Fixed Label constrained to the trailing edge... I assume you want it left-aligned with Date Label

    3. When creating your CustomViews, you were setting a height constraint of 100 -- which defeats the purpose of allowing the content to determine the size.

    4. In CustomView class, you had contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] commented out. That line should be there.

    5. In your view controller, you added a height constraint to contentView with a low priority. Best option is to make that a Placeholder constraint (double-click the constraint, and select the Placeholder checkbox). That way the constraint is removed at run-time, but is there during design (and Storyboard doesn't complain).

    6. You were doing a few other un-necessary things - likely you were trying different stuff to get it to work.

    7. The view setup (adding your views) is best done in viewDidLoad() -- definitely not in viewDidLayoutSubviews()

    8. I'm guessing that, in your CustomView, instead of an explicit width of 200 you probably want to constrain the Date Label leading and trailing, allowing it to horizontally stretch based on the device width... but I left it at 200.

    If you can follow that information, you should be able to fix the issue(s). But, I put the project up as a GitHub repo for you, so you can get it in a "working" state, and so you can see the changes.

    Here's the link to the repo: https://github.com/DonMag/ATester2

    Here is the result:

    enter image description here

    And scrolled up a bit:

    enter image description here