SwiftUI - 同时动画视图转换和位置更改

SwiftUI - Animate view transition and position change at the same time

我有一个黄色的容器,里面是绿色的。我想移动容器,同时 hiding/showing 内部绿色视图,带有动画。目前,我正在使用 .offset 进行移动,并使用 if 语句进行绿色视图的转换。

问题是,虽然黄色容器移动了,但绿色视图没有移动。它只是在目标偏移处淡入淡出。我希望它也能与黄色容器一起移动。

This is what I get currently This is what I want

这是我的代码:

struct ContentView: View {
    @State var showingSubview = false
    
    var body: some View {
        VStack {
            Button("Show Subview") {
                withAnimation(.easeInOut(duration: 2)) {
                    showingSubview.toggle()
                }
            }
            
            if showingSubview {
                Text("Subview")
                    .padding()
                    .background(Color.green)
            }
        }
        .padding()
        .background(Color.yellow)
        .offset(x: showingSubview ? 150 : 0, y: 0)
    }
}

如何让绿色视图随着黄色容器一起淡入淡出移动?最好,我想继续对 insertion/removal.

使用 ifswitch 语句

您可以在动画时更改高度。

代码版本 #1

这不会褪色并出现在黄色矩形内。

代码:

struct ContentView: View {
    @State var showingSubview = false

    var body: some View {
        VStack(spacing: 0) {
            Button("Show Subview") {
                withAnimation(.easeInOut(duration: 2)) {
                    showingSubview.toggle()
                }
            }

            Text("Subview")
                .padding()
                .background(Color.green)
                .padding(.top)
                .frame(height: showingSubview ? nil : 0, alignment: .top)
                .clipped()
        }
        .padding()
        .background(Color.yellow)
        .offset(x: showingSubview ? 150 : 0, y: 0)
    }
}

结果#1

代码版本 #2

此版本将淡出并出现在底部边缘,如您的 GIF 所示。

代码:

struct ContentView: View {
    @State var showingSubview = false

    var body: some View {
        VStack(spacing: 0) {
            Button("Show Subview") {
                withAnimation(.easeInOut(duration: 2)) {
                    showingSubview.toggle()
                }
            }

            Text("Subview")
                .padding()
                .background(Color.green)
                .padding(.top)
                .frame(height: showingSubview ? nil : 0, alignment: .top)
                .padding(.bottom)
                .background(Color.yellow)
                .clipped()
                .opacity(showingSubview ? 1 : 0)
        }
        .padding([.horizontal, .top])
        .background(Color.yellow)
        .padding(.bottom)
        .offset(x: showingSubview ? 150 : 0, y: 0)
    }
}

结果#2