首页 > 解决方案 > 当视图在 SwiftUI 中呈现时,视图的不同元素的不同转换

问题描述

因此,当在 SwiftUI 中呈现视图时,我试图以不同的方式显示不同的元素(一个是从前缘滑入,另一个元素是从屏幕底部向上滑动)。我的基本视图结构如下:

struct ViewName: View {
  @ObservedObject var appState: AppState //this is just a class that tracks the state of app variables, in my case it holds a variable called 'showView' that indicates whether or not to show the view.
  var body: some View {
    ZStack {
      Color.white
        .edgesIgnoringSafeArea(.all)
      VStack {
        Text("Test")
      }.transition(AnyTransition.asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing)))
      VStack {
        Spacer()
        HStack {
          Text("Test2")
          Spacer()
          Text("Test3")
        }
      }.transition(AnyTransition.move(edge: .bottom))
    }
  }
}

在其他地方,我将视图初始化为:

if appState.showView {
  ViewName(appState: appState)
}

和一个改变是否显示视图的按钮:

Button(action: {
  withAnimation {
    appState.showView.toggle()
  }
}, label: { 
  Text("Click me") 
})

看起来 Swift 不知道如何处理这两个过渡,并且它有点默认它们都为淡入不透明过渡。不知道如何解决这个问题。非常感谢任何帮助!

标签: swiftxcodeanimationswiftuitransition

解决方案


问题是你只有 1 if appState.showView {

if appState.showView {
    ViewName(appState: appState)
}

结果,SwiftUI 仅使用默认的淡入淡出过渡(因为您没有指定)动画整个进出。 ViewName

相反,您需要if appState.showView {在要设置动画的每个单独元素上使用。

class AppState: ObservableObject {
    @Published var showView = false
}

struct ContentView: View {
    @StateObject var appState = AppState()
    var body: some View {
        VStack {
            Button(action: {
                withAnimation {
                    appState.showView.toggle()
                }
            }, label: {
                Text("Click me")
            })
            
            ViewName(appState: appState) /// just make this always showing
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.green)
    }
}

struct ViewName: View {
    @ObservedObject var appState: AppState
    var body: some View {
        ZStack {
            if appState.showView { /// need this, so `ViewName` will be invisible when `appState.showView` is false
                Color.white
                .edgesIgnoringSafeArea(.all)
                /// optional: add a transition here too
                /// by default, it will fade
            }
            
            if appState.showView { /// need this!
                VStack {
                    Text("Test")
                }
                .zIndex(1) /// needed for removal transition
                .transition(AnyTransition.asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing)))
            }
            
            if appState.showView { /// need this!
                VStack {
                    Spacer()
                    HStack {
                        Text("Test2")
                        Spacer()
                        Text("Test3")
                    }
                }
                .zIndex(2) /// needed for removal transition
                .transition(AnyTransition.move(edge: .bottom))
            }
        }
    }
}
过渡工作

推荐阅读