简体   繁体   English

SwiftUI:用 crossDissolve 样式替换数组视图 animation

[英]SwiftUI: Replace view of array with crossDissolve style animation

I have a view with dynamic content.我有一个动态内容的视图。 I want to add an animation (fadeOut/fadeIn) to switch to the next view我想加一个animation(fadeOut/fadeIn)切换到下一个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但是不起作用,我从上到下得到一张幻灯片 animation

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()
                    })
            }
        }
    }
}

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.所以我猜 animation 不喜欢与 AnyView 类型擦除一起工作。

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()
                })
            }
        }
    }
}

I found a workaround that simule crossDissolve animation:我找到了一个模拟 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)))
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM