【问题标题】:SwiftUI - Animate view transition and position change at the same timeSwiftUI - 同时动画视图过渡和位置变化
【发布时间】:2021-12-07 00:42:45
【问题描述】:

我有一个黄色的容器,里面有一个绿色的视图。我想移动容器,同时隐藏/显示内部绿色视图,并带有动画。目前,我使用.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)
    }
}

如何让绿色视图随着黄色容器一起移动,因为它淡入淡出?最好是继续使用ifswitch 语句进行插入/删除。

【问题讨论】:

  • 你还没有得到第二个 GIF 中显示的工作代码吗?或者我错过了什么:p
  • @George 不幸的是,这只是我在 Figma 中制作的原型

标签: ios swift swiftui swiftui-animation


【解决方案1】:

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

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

【讨论】:

  • 嗯,所以在开始渲染子视图并使其透明?我本来想使用if,但如果这是唯一的方法,那对我来说已经足够了。还有fixedSize 是干什么用的?没有它我得到相同的结果。
  • @aheze 是的,你说得对,可以删除 fixedSize。我在解决它时正在使用它,但没有意识到不再需要它。 if 不起作用,因为那时您只是从视图进入或离开层次结构时开始制作动画 - 这不会改变其位置。请记住,从技术上讲,这些属性会立即更改,但 SwiftUI 只是为可见更改设置动画。将不透明度设置为 0 与将其从层次结构中移除相比,性能差异应该可以忽略不计(尽管我实际上不知道哪个会更快,因为优化了具有 0 不透明度的视图)。
  • @aheze:但乔治的回答如何解决您的问题/疑问?我的意思是你有if 在视图中,但答案从一开始就一直呈现该文本。
  • @swiftPunk 是的,答案并不是我想要的。不过目前好像没有别的办法了。
猜你喜欢
  • 2020-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-17
相关资源
最近更新 更多