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

chr*_*epe 2 animation transition swift swiftui

背景:我在使用SwiftUI Transitions. 我有一个FormView包含 4 个不同的Sub-Forms. 当用户按下 时Next-Button,下一个Sub-Form View会出现Transition (.move -> 从右到左)

我也有一个Back Button. 当用户按下此按钮时,Sub-Form View将显示上一个,当前具有相同的Transition (.move -> 从右到左)。但是,我想将Transition本例中的(.move -> left to right)反转为 (.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()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:正如您所看到的,无论您前后导航,都Transition将始终是right to left。我怎样才能实现改变Transition取决于哪个Button被按下的目标?

use*_*ser 5

这是一个适合您的方法:

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") })
    }
    
}
Run Code Online (Sandbox Code Playgroud)