Complex layout in Unity

Complex layout in Unity

I need ScrollRect, but at startup I don't know how many elements it should keep. Moreover this elements should be kept in categories that can fold/unfold.

The problem is that height of content doesn't updates after folding/unfolding. This worked in Unity 5 with ContentSizeFitter in content and each category, but this doesn't work with Unity 2017.
Items are added at runtime with instantiating from prefab in a certain category.
Is there any solutions without additional scripting?
EDIT
Additional screenshots

When unfolded can't scroll anything because content size is too small

This is script part for instantiating items inside categories.

Solutions/Answers:

Answer 1:

“Children should also have a ContentSizeFitter to change their height in order for parent ContentSizeFitter to change its height.” – that was my mistake. It’s not true that children should have it. What is important is that ContentSizeFitter – doesn’t have a clue what behaviour it should use to fit all the content. For example, you have multiple child elements with width: 100 and height: 50, you have 3 of them. They are all placed in content that has ContentSizeFitter on it. While you would expect ContentSizeFitter to add all the bounding boxes and calculate it’s own bounding box it doesn’t do that.

Content Fitter Example

Why? – Because it needs some kind of trigger that will define it’s behaviour.

And what can serve as this trigger? – Layout components.

Vertical Group + Content Fitter

LayoutGroup component tells ContentSizeFitter that it has this width and this height or (it depends on internal implementation) ContentSizeFitter gets width and height from some Layout Group that calculates those bounds. It’s worth a try to create a custom LayoutGroup component that calculates bounds as required for your project. But in most cases Grid, Vertical and Horizontal are enough to achieve the desired results.

If native component doesn’t work as required then you may as well write your own, or extend the behaviour of a current one.

Here is an example of how additional functionality can be added to the component:

[AddComponentMenu("Layout/Advanced Content Size Fitter", 141)]
[ExecuteInEditMode]
public class AdvancedContentSizeFitter : ContentSizeFitter
{
    protected RectTransform m_rectTransfrom;

    [SerializeField] protected Vector2 m_minSize = new Vector2(0f, 0f);
    [SerializeField] protected Vector2 m_maxSize = new Vector2(250f, 250f);

    protected override void OnRectTransformDimensionsChange()
    {
        base.OnRectTransformDimensionsChange();

        if (this.m_rectTransfrom == null)
            this.m_rectTransfrom = this.transform as RectTransform;

        this.m_rectTransfrom.sizeDelta = new Vector2(Mathf.Clamp(this.m_rectTransfrom.sizeDelta.x, this.m_minSize.x, this.m_maxSize.x), Mathf.Clamp(this.m_rectTransfrom.sizeDelta.y, this.m_minSize.y, this.m_maxSize.y));
    }

    protected override void OnEnable()
    {
        base.OnEnable();

        this.m_rectTransfrom = this.transform as RectTransform;
    }
}

This one basically adds min, max size to the component behaviour while keeping the previous behaviour.

References