Search code examples
iosautolayout

Multiple flexible height items - how to set the autolayout priorities?


Say you have (for example) a table cell layout with more than one dynamic flexible-height items,

They are linked vertically one to the other in the obvious way.

enter image description here

It seems very difficult to make this work, and very undocumented.

You'd expect that: you set the compression resistance of all the expandable items to 751. But that doesn't work.

After random experimentation, it seems to me that surprisingly you have to do something like this:

have the compression/hugging of the overall view on 250 and 750,

enter image description here

then strangely enough, for the three text views in the example, the priorities have to

...sequentially increase...

enter image description here

And, I think you have to make one of them "one lower" than the overall view - in the example one of them would be 749.

It's difficult/impossible to find the exact "formula" to make it work consistently.

What the heck is the logic of this? Is it just a pure bug in iOS?

Has anyone found the "correct formula" for making a number of expandables work in a cell?

  • priorities for the three text views

  • priorities for the overall holder view

cheers


Solution

  • Your question is not very clear to me. However, here's a good recipe to stack text views (whether or not you use a stack view for constraining them doesn't matter):

    1. Disable scrolling for all your UITextViews:

    Disable scrolling in Identity Inspector

    Reason: If scrolling is enabled, a UITextView does not have a defined intrinsicContentSize. See this answer. Without an instrinsic content size, the content hugging and compression resistance ("CHCR") priorities have no meaning or effect.

    2. Give each view along one axis a different priority for CHCR:

    More precisely: Give all views that are connected with constraints along one axis a different CHCR priority that are not constrained in size along that axis (i.e. that don't have a fixed width / height constraint).

    In your particular example, your setup shown in the screenshots is a correct solution: Each of the three text views has a different content hugging and a different compression resistance priority. As a general rule you should start with the default values (750 / 250) and only slightly increase or decrease them as you did.

    In case you use a table view with self-sizing cells (by setting its estimatedItemSize), the CHCR priorities won't matter at runtime because the cell will automatically resize to accommodate enough space for all three text views. You just need to set those priorities to "silence" Interface Builder.

    If you use fixed-height table view cells however, the CHCR priorities are quite important because they determine

    • which of the views will shrink first if there's not enough space inside the cell (it's the view with the lowest compression resistance priority) and
    • which of the views will expand if there's more space inside the cell than the subviews actually need (it's the view with the lowest content hugging priority).

    The CHCR priorities of the superview ("MV") is irrelevant as it's usually just a container view that does not have a defined intrinsicContentSize either. Its size is defined by the inner and outer constraints you add.


    For more information on the CHCR priorities, see the chapter Intrinsic Content Size in the Auto Layout Guide.