Search code examples
swiftswiftuiswift3swiftui-view

How do I prevent SwiftUI View from taking up any space?


I’m pretty new to SwiftUI and am working on this little project. I want to place an image either on top of or between lines, depending on the position variable.

struct ContentView: View {
   @State var position = 5

   var body: some View {
        VStack(spacing: 20){
            ForEach(1...15, id: \.self){i in
                ZStack{
                    if i%2 != 0{
                        Rectangle()
                            .frame(height: 4)
                            .foregroundColor(.white)
                    }
                    if i == position{
                        Circle()
                            .frame(height: 30)
                            .foregroundColor(.white)
                    }
                }
            }
        }
    }
}

This is the result ContentViewImage:-

Screenshot

If i is odd, we create a line. If i equals position, we create a circle on top of the line or if we didn’t create a line the circle will be drawn between the other lines.

My problem with this is that the lines don’t stay still when I change the value of position.* This is because the circle takes up space and pushes the lines away from it. The lines above and below the circle gets pushed away more when the circle is between two lines which causes the lines to kind of go back and forth as I change from between to on top of lines.

How would I go about fixing this?


Solution

  • There is two issues here: non-constant height of row (because row with circle and w/o circle have different heights) and conditional layout (absent rectangles gives different layout).

    Here is a possible solution. Tested with Xcode 13.4 / iOS 15.5

    demodemo1

    struct ContentView: View {
       @State var position = 4
    
       var body: some View {
            VStack(spacing: 20){
                ForEach(1...15, id: \.self){i in
                    ZStack {
                        Rectangle()
                            .frame(height: 4)
                            .foregroundColor(i%2 == 0 ? .clear : .white)  // << here !!
                        if i == position{
                            Circle()
                                .foregroundColor(.white)
                                .frame(height: 30)
                        }
                    }.frame(height: 4)    // << here !!
                }
            }
        }
    }