SwiftUI:如何根据状态对象创建自定义 SwiftUI 转换?

SwiftUI: How to create a custom SwiftUI Transition depending on a State Object?

上下文:我在使用 SwiftUI Transitions 时遇到问题。我有一个 FormView 包含 4 个不同的 Sub-Forms。当用户按下 Next-Button 时,下一个 Sub-Form View 会显示 Transition (.move -> right to left).

我也有一个Back Button。当用户按下此按钮时,将显示之前的 Sub-Form View,当前具有相同的 Transition (.move -> right to left)。但是,我想在这种情况下将 Transition 反转为 (.move -> left to right).


代码

enum FormStep {
    case step1, step2, step3, step4
}

struct CustomForm: View  {
    @State private var step: FormStep = .step1

    var body: some View {
        // This Button will change the step State to the previous step
        Button(action: { withAnimation { previousStep() } } { Text("Previous") }

        // This is the Right to Left Transition applied to subForm
        subForm
            .transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)))

        // This Button will change the step State to the next step
        Button(action: { withAnimation { nextStep() } } { Text("Next") }
    }

    @ViewBuilder private var subForm: some View {
        switch medicationFormVM.step {
        case .step1: StepOneSubForm()
        case .step2: StepTwoSubForm()
        case .step3: StepThreeSubForm()
        case .step4: StepFourSubForm()
        }
    }
}

问题: 如您所见,无论您是来回导航,Transition 始终是 right to left。我怎样才能根据按下的 Button 来实现更改 Transition 的目标?

这里有一个适合你的方法:

enum FormTransition {
    case next, back
    var value: AnyTransition {
        switch self {
        case .next:
            return AnyTransition.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading))
        case .back:
            return AnyTransition.asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing))
        }
    }
}

struct CustomForm: View  {
    
    @State private var step: FormStep = .step1
    @State private var transition: AnyTransition = FormTransition.next.value
    
    var body: some View {
        
        Button(action: { transition = FormTransition.back.value; withAnimation { previousStep() } } { Text("Previous") })
        
        subForm
            .transition(transition)
        
        Button(action: { transition = FormTransition.next.value; withAnimation { nextStep() } } { Text("Next") })
    }
    
}