SwiftUI 条件视图不会动画/过渡

27

我正在尝试使用视图上的 .transition() 实现动画/过渡效果。我使用了来自这里的类似代码,并将 .transition() 应用到两个有条件的视图中。

struct Base: View {
    @State private var isSignedIn = false

    var body: some View {
        Group {
            if(isSignedIn){
                Home().transition(.slide)
            }else{
                AuthSignin(isSignedIn: self.$isSignedIn).transition(.slide)
            }
        }
    }
}

struct AuthSignin: View {
    @Binding var isSignedIn: Bool

    var body: some View {
        VStack {
            Button(action: {
                self.isSignedIn = true
            }) {
                Text("Sign In")
                    .bold()
                    .frame(minWidth: CGFloat(0), maxWidth: .infinity)
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(Color.white)
                    .cornerRadius(CGFloat(10))
            }.padding()
        }
    }
}

不过,每当我点击“登录”按钮(无论是否使用.transition()),应用程序都会冻结一秒钟,然后Home()视图将突然出现,没有任何动画/转换。我还尝试将self.isSignedIn = true包装在withAnimation中,但它仍然无法正常工作。有什么建议或更好的方法吗?

3个回答

19

.transition添加到切换视图的容器中,而不是每个条件视图上。以下是我完成的一些代码的一个微不足道的示例(可以正常工作)。

在需要有条件转换的主要视图中:

import SwiftUI

struct AppWrapperView: View {

  @State var showFirstRun:Bool = true

  var body: some View {
    ZStack {
      if (showFirstRun) {
        FirstRunView(showFirstRun: $showFirstRun)
      } else {
        Text("Some other view")
      }
    }
    .transition(.slide)
  }
}

然后,在触发条件变化的视图中的某个位置:

import SwiftUI

struct FirstRunView: View {

  @Binding var showFirstRun:Bool

  var body: some View {

    Button(action: {
      withAnimation {
        self.showFirstRun = false
      }
    }) {
      Text("Done")
    }
  }
}

3
对我来说不起作用 :( 我正在尝试模仿Google地图应用程序,在那里,当您按下搜索字段时,会呈现带有淡入淡出(不透明度)转换的叠加视图。因此,仅当将转换应用于“第二”视图并仅以显示形式(没有动画地解除显示)时才有效,但是如果将其应用于ZStack,则根本无法工作。 - Serj Rubens
可行的解决方案是将zIndex添加到至少要呈现的“Second”视图中,或者更好的是将其添加到所有ZStack视图中。看起来像是一个错误。在这里找到了它:https://dev59.com/GVMH5IYBdhLWcg3w4U95 - Serj Rubens

18

我不得不将我的if..else语句放在ZStack容器内而不是Group中。看起来Group在我的情况下是破坏动画的主要原因。此外,我将.transition.animation结合应用于容器而不是视图。

ZStack {
  if(isSignedIn){
    Home()
  } else {
    AuthSignin(isSignedIn: self.$isSignedIn)
  }
}
.transition(.slide)
.animation(.easeInOut)

4
使用ZStack代替Group就解决了问题 - 谢谢。 - Peter
1
将Group替�为ZStack也解决了我的问题�谢谢这个�示�👨�💻 - Serzhas
4
在使用ZStack时,要注意.zIndex()。如果将超过1个视图放置在ZStack中,则可能会出现动画仅在出现时播放,而在消失时不播放的情况。原因是视图在ZStack中的位置。当一个视图被解除显示时,它会被放置在ZStack中所有其他视图的后面。 为避免任何类型的动画问题,请设置ZStack中每个视图的.zIndex。还应避免将索引设为0。 - cseh_17
截至2023年7月22日,集团正在为我工作,而不是ZStack。 - Plato

-2

在 self.isSignedIn = true 之前加上 WithAnimation


是的,我已经尝试过像我之前提到的那样,在withAnimation中包装self.isSignedIn = true,但仍然无效。现在问题似乎是每当加载一个未显示的新复杂视图(例如Home())时,会出现2秒的冻结。因此没有动画效果。 - leftysauce
1
那么你应该展示给我们你复杂的主页视图,问题一定出在那里。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接