ios SwiftUI:将数组视图替换为crossDissolve样式动画

8ljdwjyq  于 2022-12-15  发布在  iOS
关注(0)|答案(2)|浏览(146)

我有一个包含动态内容的视图。我想添加动画(淡入/淡出)以切换到下一个视图
为此,我尝试:

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

但不起作用,我得到一个幻灯片动画从上到下
我的当前代码:

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

elcex8rz1#

我对您的代码做了一个抽象,它显示转换确实适用于相同的底层视图类型(文本),但不适用于不同的视图类型(如昵称和默认值)。
所以我猜动画不喜欢与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()
                })
            }
        }
    }
}
1l5u6lss

1l5u6lss2#

我找到了一个模拟crossDissolve动画解决方法:

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

相关问题