SwiftUI -动画视图过渡和位置更改在同一时间

jecbmhm3  于 2023-04-28  发布在  Swift
关注(0)|答案(2)|浏览(170)

我有一个黄色的容器里面有绿色的视野。我想移动容器,同时隐藏/显示内部绿色视图,并显示动画。目前,我正在使用.offset进行移动,并使用if语句进行绿色视图的转换。
问题是,虽然黄色容器移动,但绿色视图不移动。它只是在目标偏移处淡入淡出。我希望它也能沿着黄色容器移动。
| 这是我目前得到的|这就是我想要的|
| --------------|--------------|
|

|

|
下面是我的代码:

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)
    }
}

如何使绿色视图沿着黄色容器的淡入淡出而移动?最好,我想继续使用ifswitch语句进行插入/删除。

tgabmvqs

tgabmvqs1#

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

代码版本#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

mzaanser

mzaanser2#

一年后找到了一个解决方案,它真的很简单-只需添加.scaleEffect(1)

.clipped() /// prevent the green view from overflowing
.scaleEffect(1) /// the magic modifier!

这是一个更干净的解决方案,不涉及设置自定义帧或其他任何东西。此外,它还适用于ifswitch语句!

我不完全确定.scaleEffect(1)为什么工作,但它与SwiftUI如何组合视图有关。我认为修改器使SwiftUI将其呈现为一个新组?如果有人知道原因,我会很感激的。
下面是完整的代码:

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)
        .clipped() /// 1.
        .scaleEffect(1) /// 2.
        .offset(x: showingSubview ? 150 : 0, y: 0)
    }
}

相关问题