'SwiftUI view layouts with frame maxHeight and .infinity

How to layout views in SwiftUI in such way

  1. I have input fields that I want to stretch to fill available space
  2. This inputs are placed in VStack in such way that I am giving them frame(height: 40)
  3. This VStack is inside white box which has frame(maxHeight: geometry.size.height * 0.8)

And the last white box is not adjusting to number of inputs in for VStack but rather takes 0.8 space and then this inputs are spread inside VStack instead (more spacing than needed is added.

I do not understand why such thing is happening.

FormView()
     .frame(
       maxWidth: geometry.size.width * 0.85,
        maxHeight: geometry.size.height*0.85
)

Form View contains:

 VStack(spacing: 4) {
            FormInput(label: "First Name", input: self.$firstName) {
                isEditing in

                self.avoider.editingField = 0
            }
            .frame(height: 40)
            .padding(0)
            .avoidKeyboard(tag: 0)


Solution 1:[1]

I found the reason why sometimes View (layout) does not collapse to take smallest possible space, but instead expands to maxHeigh/maxWidth.

It happens when somewhere in between we use

GeometryReader { geometry in

    VStack { ... }

}

Then those Views does not collapse and spread to maxHeight. I have this GeometryReader used inside .avoidKeyboard(tag: 0)

Solution 2:[2]

I also experienced this issue but managed to fix it by specifying idealHeight instead maxHeight and also adding a minHeight. So your example would be something like:

FormView()
     .frame(
       maxWidth: geometry.size.width * 0.85,
       idealHeight: geometry.size.height * 0.85,
       minHeight: geometry.size.height * 0.6
)

On a device with enough space, the ideal height will be used, on smaller devices the height will shrink but not to less than minHeight.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Michał Ziobro
Solution 2 Johannes