Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI. How to set shrink behavior for Spacer?

How to set default spacing between rgb views (100pt) if their container (VStack) not conflicts with bottom black view.(like iPhone 11 Pro Max). BUT shrinks if there is no space for 100p height.(like iPhone SE on the screenshot)

My code:

struct ContentView: View {
    var body: some View {
        VStack(spacing: 0) {
            VStack(spacing: 0) {
                Rectangle()
                    .foregroundColor(.red)
                    .frame(height: 100)
                Spacer()
                    .frame(minHeight: 10, maxHeight: 100)
                Rectangle()
                    .foregroundColor(.green)
                    .frame(height: 100)
                Spacer()
                    .frame(minHeight: 10, maxHeight: 100)
                Rectangle()
                    .foregroundColor(.blue)
                    .frame(height: 100)
            }
            Spacer()
                .frame(minHeight: 10, maxHeight: 600)
            Rectangle() // keyboard
                .frame(height: 200)
        }
    }
}

So the problem is: Spacers with maxHeight: 100 have height = 10 (not 100) on iPhone 11 Pro Max. (BUT space between black view and VStack allows it)

How to make behavior I explained?

enter image description here

enter image description here

like image 762
Igor Kasuan Avatar asked Dec 02 '19 09:12

Igor Kasuan


People also ask

How do you make a spacer smaller in SwiftUI?

If you want to make a spacer of an exact size, just do the same thing you would do for any other kind of view: use a frame() modifier with the exact sizes you want. If you give the spacer a range of values, for example using .

What is spacer ()?

Spacer creates an adjustable, empty spacer that can be used to tune the spacing between widgets in a Flex container, like Row or Column. The Spacer widget will take up any available space, so setting the Flex. mainAxisAlignment on a flex container that contains a Spacer to MainAxisAlignment.

What is VStack in Swift?

VStack allows to arrange its child views in a vertical line, and ZStack allows to overlap its child views on top of each other. Stacks can further be customized with alignment and spacing in order to modify their appearance.


2 Answers

You need to use idealHeight alongside with .fixedSize modifier for Spacers:

Spacer()
    .frame(minHeight: 10, idealHeight: 100, maxHeight: 600)
    .fixedSize()
like image 74
Mojtaba Hosseini Avatar answered Oct 03 '22 04:10

Mojtaba Hosseini


Use Spacer(minLength: 10) for the last spacer.

struct ContentView: View {
    var body: some View {
        VStack(spacing: 0) {
            VStack(spacing: 0) {
                Rectangle()
                    .foregroundColor(.red)
                    .frame(height: 100)
                Spacer()
                    .frame(minHeight: 10, maxHeight: 100)
                Rectangle()
                    .foregroundColor(.green)
                    .frame(height: 100)
                Spacer()
                    .frame(minHeight: 10, maxHeight: 100)
                Rectangle()
                    .foregroundColor(.blue)
                    .frame(height: 100)
            }
            Spacer(minLength: 10)
            Rectangle() // keyboard
                .frame(height: 200)
        }
    }
}

The problem in your code is that when you wrap a Spacer inside a frame like Spacer().frame(minHeight: 10, maxHeight: 600), it is first considered as a frame, then a Spacer inside that frame. And a frame has equal default layout priority as other views. So the parent will propose it the same amount of space as the inner VStack. By removing the frame modifier, the Spacer has the least layout priority, so the inner VStack will take as much space as possible except the minimum 10 points claimed by the spacer and 200 points for the rectangle.

like image 33
Cosyn Avatar answered Oct 03 '22 05:10

Cosyn