【问题标题】:Broken Animation SwiftUI破碎的动画SwiftUI
【发布时间】:2020-02-29 10:25:54
【问题描述】:

我最初有这个问题here。 @arsenius 提出的解决方案适用于这个玩具示例。然而,我的应用程序更复杂,我花了很长时间才找出动画中断的地方。在示例中,我使用了两个动​​画HStack。但是,如果我将这些 HStack 替换为 两个不同的 (!) 自定义视图,动画就会再次损坏。

代码如下:

class State:ObservableObject{
    @Published var showSolution = false
}

struct ContentView: View {
    @EnvironmentObject var state:State

    var body:some View {
        VStack {
            if state.showSolution{
                CustomToggleOne()
                    .background(Color.red)
                    .id("one")
                    .animation(Animation.default)
                    .transition(.slide)
            } else {
                CustomToggleTwo()
                    .background(Color.yellow)
                    .id("two")
                    .animation(Animation.default.delay(2))
                    .transition(.slide)
            }
        }
    }
}

struct CustomToggleOne: View{
    @EnvironmentObject var state:State

    var body:some View{
        HStack{
            Spacer()
            Button(action:{
                withAnimation {
                    self.state.showSolution.toggle()
                }
            }){
                Text("Next")
            }.padding()
            Spacer()
        }
    }
}

struct CustomToggleTwo: View{
    @EnvironmentObject var state:State

    var body:some View{
        HStack{
            Spacer()
            Button(action:{
                withAnimation {
                    self.state.showSolution.toggle()
                }
            }){
                Text("Next")
            }.padding()
            Spacer()
        }
    }
}

我将State 的一个实例添加到SceneDelegate.swift 中的ContentView 作为EnvironmentObject,如下所示:

let contentView = ContentView().environment(\.managedObjectContext, context).environmentObject(State())

当我们在ContentView 中使用两次CustomToggleOne() 而不是CustomToggleTwo() 时,可以看到预期的动画。

【问题讨论】:

    标签: swift animation swiftui


    【解决方案1】:

    这是正确的方法,下面和 cmets 中的一些解释。使用 Xcode 11.2 / iOS 13.2 测试

    提醒:不要在预览中测试过渡 - 仅在模拟器或设备上

    // !! Don't name your types as API,
    // State is SwiftUI type, might got unpredictable weird issues
    class SolutionState:ObservableObject{
        @Published var showSolution = false
    }
    
    struct TestBrokenAnimation: View {
        @EnvironmentObject var state:SolutionState
    
        var body:some View {
            VStack {
                if state.showSolution{
                    CustomToggleOne()
                        .background(Color.red)
                        .id("one")
                        .transition(.slide) // implicit animations confuse transition, don't use it
                } else {
                    CustomToggleTwo()
                        .background(Color.yellow)
                        .id("two")
                        .transition(.slide)
                }
            }
        }
    }
    
    public func withAnimation<Result>(_ animation: Animation? = .default, 
                  _ body: () throws -> Result) rethrows -> Result
    

    正如它所看到的withAnimation 不是状态,它只是激活通过修饰符定义的动画,它显式应用指定的动画,拥有,所以在修饰符中添加更多肯定会导致一些冲突。

    所以使用带有过渡的显式动画。

    struct CustomToggleOne: View{
        @EnvironmentObject var state:SolutionState
    
        var body:some View{
            HStack{
                Spacer()
                Button(action:{
                    withAnimation(Animation.default.delay(2)) {
                        self.state.showSolution.toggle()
                    }
                }){
                    Text("Next")
                }.padding()
                Spacer()
            }
        }
    }
    
    struct CustomToggleTwo: View{
        @EnvironmentObject var state:SolutionState
    
        var body:some View{
            HStack{
                Spacer()
                Button(action:{
                    withAnimation() {
                        self.state.showSolution.toggle()
                    }
                }){
                    Text("Next")
                }.padding()
                Spacer()
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多