skip to Main Content

I have a view with dynamic content.
I want to add an animation (fadeOut/fadeIn) to switch to the next view

For this purpose I tried:

.transition(.opacity)
.animation(.easeInOut, value: tabSelection)

But doesn’t work, I get a slide animation from top to bottom

My current code:

struct LongOnboardingContainerView: View {

    @State var tabSelection = 0

    var body: some View {
            ZStack {
                Step.allCases[tabSelection].view {
                    tabSelection += 1
                }
                .transition(.opacity)
                .animation(.easeInOut, value: tabSelection)
        }
        .ignoresSafeArea(.all)
    }

    enum Step: Int, CaseIterable {
        case parentsGoal, nickname, age, mathSkills, languageSkill

        func view(pushNext: @escaping () -> ()) -> AnyView {
            switch self {
                case  parentsGoal mathSkills, languageSkill:
                    return AnyView(MultiAnswerView(viewModel: .init(step: self), pushNext: pushNext))
                case .nickname:
                    return AnyView(NickNameController.swiftUIRepresentation { vc in
                        vc.nextHandler = pushNext
                    })
                default:
                    return AnyView(Text("Test").onTapGesture {
                        pushNext()
                    })
            }
        }
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    I found a workaround that simule crossDissolve animation:

        @State var tabSelection = 0
        @State var isVisible = true
    
        var body: some View {
            ZStack {
                 if isVisible {
                    stepView()
                } else {
                    stepView()
                }    
            }
            .ignoresSafeArea(.all)
        }
        
    func stepView() -> some View {
        Step.allCases[tabSelection].view {
            tabSelection += 1
            isVisible.toggle()
        }
        .transition(AnyTransition.opacity.animation(.easeInOut(duration: 0.35)))
    }
    

  2. I did an abstraction of your code and it shows that the transition does work with same underlying view types (Text), but does not with different ones (as for nickname and default).

    So I guess the animation doesn’t like to work together with AnyView type erasure.

    let colors: [Color] = [.red, .yellow, .blue, .green, .teal, .gray]
    
    struct ContentView: View {
    
        @State var tabSelection = 0
    
        var body: some View {
                ZStack {
                    Step.allCases[tabSelection].view {
                        tabSelection =  (tabSelection + 1) % Step.allCases.count
                    }
                    .transition(.opacity)
                    .animation(.easeInOut(duration: 1), value: tabSelection)
            }
            .ignoresSafeArea(.all)
        }
    
    
        enum Step: String, CaseIterable {
            case parentsGoal, nickname, age, mathSkills, languageSkill
    
            
            func view(pushNext: @escaping () -> ()) -> AnyView {
                switch self {
                case  .parentsGoal, .mathSkills, .languageSkill:
                    return AnyView(
                        Text("Multi Answer View (self.rawValue)").font(.largeTitle)
                            .onTapGesture {  pushNext() }
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(colors.randomElement()!)
                    )
                case .nickname:
                    return AnyView(
                        VStack {
                            Image(systemName: "person")
                            Text("Nickname View").font(.largeTitle)
                        }
                            .onTapGesture {  pushNext() }
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(.orange)
                    )
                default:
                    return AnyView(Text("Test").onTapGesture {
                        pushNext()
                    })
                }
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search