When move view by offset with animation, subview animating individually

Viewed 17

Im trying to move cell view by offset with animation.
I thought Test Text will move with superview but when middle of the moving down, Test Text deviate from position.
I think Text animating individually but i cant understand why.
I might not understand well about relation between animating and subviews.
Can someone tell how animating effect to subview and how to fix Test Text Location when moving superview?

https://i.stack.imgur.com/1bA5H.gif

let SAFEAREA_BOTTOM = UIApplication.shared.connectedScenes
    .compactMap({ $0 as? UIWindowScene })
    .flatMap({ $0.windows })
    .first(where: { $0.isKeyWindow })?
    .safeAreaInsets.bottom ?? 0

struct TestView: View {

    @State var extend: Bool = false
    @State var cellFrame: CGRect = .zero
    @State var offsetY: CGFloat = 0
    
    var body: some View {
        VStack {
            cell
            Spacer()
        }
    }
    
    var cell: some View {
        VStack(spacing: 0) {
            HStack {
                Text("Test")
                Spacer()
            }
            
            VStack {
                Text("Extension1")
                Text("Extension2")
            }
                .frame(height: extend ? nil : 0)
                .clipped()
            
        }.padding()
        .background(Color.green)
        .padding()
        .offset(x: 0, y: offsetY)
        .overlay( GeometryReader { receiveViewFrame($0) })
        .onTapGesture {
            withAnimation(.easeInOut(duration: 1)) {
                if extend {
                    extend = false
                    offsetY = 0
                } else {
                    extend = true
                }
            }
        }
        .onChange(of: cellFrame) { frame in
            print("onChange")
            guard extend else { return }
                withAnimation(.easeInOut(duration: 1)) {
                    offsetY = UIScreen.main.bounds.height - frame.origin.y - frame.height - SAFEAREA_BOTTOM
                }
        }
    }
    
    private func receiveViewFrame(_ g: GeometryProxy) -> some View {
        DispatchQueue.main.async {
            cellFrame = g.frame(in: .global)
        }
        return Color.clear.frame(width: g.size.width, height: g.size.height)
    }
}
0 Answers
Related