Equal Rectangles animate differently?

Viewed 54
import SwiftUI

struct GrowView: View {
    var size:CGFloat = 400
    @State var scale:CGFloat = 0
    var body: some View {
        HStack(alignment: .bottom) {
            Rectangle()
                .foregroundColor(.red)
                .frame(height: 300 * scale)
                .animation(.default)
            if true {
                Rectangle()
                    .foregroundColor(.red)
                    .frame(height: 400 * scale)
                    .animation(.default)
            }

        }.onAppear {
            self.scale = 1
        }.frame( maxHeight: 500, alignment: .bottom)
    }
}

struct GrowView_Previews: PreviewProvider {
    static var previews: some View {
        GrowView()
    }
}

Without the if block, the second Rectangle animates from bottom to top. When it is inside the If block however, it appears to draw from the top to bottom. What's going on?

1 Answers

If you find a way to make them animate into one direction (instead of thinking about why and how could) then here is a solution

Tested with Xcode 11.4 / iOS 13.4

    var body: some View {
        HStack(alignment: .bottom) {
            Rectangle()
                .foregroundColor(.red)
                .frame(height: 300 * scale)
//                .animation(.default)   // XX remove !!
            if true {
                Rectangle()
                    .foregroundColor(.red)
                    .frame(height: 400 * scale)
//                    .animation(.default) // XX remove !!
            }

        }
        .animation(.default)       // << put animation here !!!
        .onAppear {
            self.scale = 1
        }.frame( maxHeight: 500, alignment: .bottom)
    }

Update: solution for conditional second rectangle with delay

struct GrowView: View {
    var size:CGFloat = 400
    @State var scale:CGFloat = 0
    @State var showSecond = true

    var body: some View {
        HStack(alignment: .bottom) {
            Rectangle()
                .foregroundColor(.red)
                .frame(height: 300 * scale)
                .animation(.default)
            VStack {
                if showSecond {
                    Rectangle()
                        .foregroundColor(.red)
                        .frame(height: 400 * scale)
                }
            }
            .animation(Animation.default.delay(0.5))
        }
        .onAppear {
            self.scale = 1
        }.frame(maxHeight: 500, alignment: .bottom)
    }
}
Related