屏幕之间的 SwiftUI 动画不起作用

问题描述 投票:0回答:1

考虑以下简单的应用程序:

  enum Screen : Equatable {
    case blue
    case red
  }

class Router: ObservableObject {
    
    public static let shared = Router()
    
    @Published var currentScreen:Screen = .blue
    @Published var previousScreen:Screen = .blue
    
    func goToScreen(screen: Screen) {
        //I've tried with and without the animation block
        //withAnimation(.easeInOut(duration: 3.0)) {
            previousScreen = currentScreen
            currentScreen = screen
        //}
            
        
    }
}

@main
struct RouterAnimationApp: App {
    
    @ObservedObject var router = Router.shared

    var body: some Scene {
        WindowGroup {
            ZStack {
                switch(router.currentScreen) {
                case .red:
                    RedView()
                        .transition(.opacity)
                        .animation(.easeInOut(duration: 3.0), value: router.currentScreen)
                case .blue:
                    BlueView()
                        .transition(.opacity)
                        .animation(.easeInOut(duration: 3.0), value: router.currentScreen)
                }
                HStack {
                    Button(action: {
                        Router.shared.goToScreen(screen: .red)
                    }, label: {
                        Text("go to red screen")
                    })
                    Button(action: {
                        Router.shared.goToScreen(screen: .blue)
                    }, label: {
                        Text("go to blue screen")
                    })
                }
                .foregroundColor(.white)
            }
        }
    }
}

屏幕之间没有动画,只是立即变化。为什么?如何在 SwiftUI 中的屏幕(视图)之间创建自定义动画?

编辑:我也尝试过每个苹果:

extension AnyTransition {
    static var moveAndFade: AnyTransition {
        .asymmetric(
            insertion: .move(edge: .trailing).combined(with: .opacity),
            removal: .scale.combined(with: .opacity)
        )
    }
}

case .red:
    RedView()
        .transition(.moveAndFade)

   case .blue:
        BlueView()
            .transition(.moveAndFade)

仍然没有动画:(

swift animation swiftui
1个回答
0
投票

animation(...)
应放在容纳要切换入/出的
View
的容器上,而不是
View
本身。例如,这有效:

@main
struct RouterAnimationApp: App {
  
  @ObservedObject var router = Router.shared

  var body: some Scene {
      WindowGroup {
          ZStack {
              switch(router.currentScreen) {
              case .red:
                  Rectangle().fill(Color.red)
                      .transition(.opacity)
              case .blue:
                  Rectangle().fill(Color.blue)
                      .transition(.opacity)
              }
              
              HStack {
                  Button(action: {
                      Router.shared.goToScreen(screen: .red)
                  }, label: {
                      Text("go to red screen")
                  })
                  Button(action: {
                      Router.shared.goToScreen(screen: .blue)
                  }, label: {
                      Text("go to blue screen")
                  })
              }
              .foregroundColor(.white)
          }
          .animation(.easeInOut(duration: 3.0), value: router.currentScreen)
      }
  }
}

还有这个:

@main
struct RouterAnimationApp: App {
  
  @ObservedObject var router = Router.shared

  var body: some Scene {
      WindowGroup {
          ZStack {
              VStack {
                  switch(router.currentScreen) {
                  case .red:
                      Rectangle().fill(Color.red)
                          .transition(.opacity)
                  case .blue:
                      Rectangle().fill(Color.blue)
                          .transition(.opacity)
                  }
              }
              .animation(.easeInOut(duration: 3.0), value: router.currentScreen)
              
              HStack {
                  Button(action: {
                      Router.shared.goToScreen(screen: .red)
                  }, label: {
                      Text("go to red screen")
                  })
                  Button(action: {
                      Router.shared.goToScreen(screen: .blue)
                  }, label: {
                      Text("go to blue screen")
                  })
              }
              .foregroundColor(.white)
          }
      }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.