微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在@ObservedObject中使用WithAnimation

如何解决如何在@ObservedObject中使用WithAnimation

比方说,我有一个简单的个人资料屏幕,如下所示:

class Model: ObservableObject {
    @Published var isSignedIn = false
    
    init() {}
    
    func login() {
        //Some networking here
        isSignedIn = true
    }
    func logout() {
        //Some networking here
        isSignedIn = false
    }
}

struct ContentView: View {
    @Observedobject var model = Model()

    var body: some View {
        ZStack {
            //ProfileView
            vstack {
                //Some Views with WithAnimation inside
                // ...
 
                Text("Hello,Dear User!")
                Button(action: {
                    self.model.logout()
                }) {
                    Text("Sign Out")
                }
            }
            .opacity(model.isSignedIn ? 1 : 0)

            //LoginView
            vstack {
                Text("Hello,Stranger")
                Button(action: {
                    self.model.login()
                }) {
                    Text("Sign In")
                }
            }
            .opacity(model.isSignedIn ? 0 : 1)
        }
    }
}

我想将动画应用于不透明度更改。

第一种方法是使用.animation修饰符。但是它具有某些缺点:如果内部视图具有WithAnimation,它将无法正常工作-它会覆盖使用WithAnimation设置的动画。

第二种使用.onReceive方法

class Model: ObservableObject {
    @Published var isSignedIn = false
    
    init() {}
    
    func login() {
        isSignedIn = true
    }
    func logout() {
        isSignedIn = false
    }
}

struct ContentView: View {
    @Observedobject var model = Model()
    
    @State var isSignedIn = false

    var body: some View {
        ZStack {
            //ProfileView
            vstack {
                Text("Hello,Stranger")
                Button(action: {
                    self.model.login()
                }) {
                    Text("Sign In")
                }
            }
            .opacity(model.isSignedIn ? 0 : 1)
        }
        .onReceive(self.model.$isSignedIn) { value in
            withAnimation(Animation.easeIn) {
                self.isSignedIn = value
            }
        }
    }
}

有一些问题(在我看来):

  • 需要另一个@State var来处理模型中的更改
  • 每个WithAnimation块都需要单独的.onReceive

问题是:将WithAnimation应用于@Observedobject是正确的方法,还是有更好的解决方案?

解决方法

您的第一种方法可以更改,因此您无需使用其他@State属性

class Model: ObservableObject {
    @Published var isSignedIn = false
    
    init() {}
    
    func login() {
        withAnimation(Animation.easeIn) {
        isSignedIn = true
        }
    }
    func logout() {
        withAnimation(Animation.easeIn) {
        isSignedIn = false
        }
    }
}

struct SView: View {
    @ObservedObject var model = Model()

    var body: some View {
        ZStack {
            //ProfileView
            VStack {
                Rectangle()
                Text("Hello,Dear User!")
                Button(action: {
                    self.model.logout()
                }) {
                    Text("Sign Out")
                }
            }
            .opacity(model.isSignedIn ? 1 : 0)

            //LoginView
            VStack {
                Rectangle()
                Text("Hello,Stranger")
                Button(action: {
                    self.model.login()
                }) {
                    Text("Sign In")
                }
            }
            .opacity(model.isSignedIn ? 0 : 1)
        }

    }
}
struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SView()
    }
}

在第二种方法中,您需要进行更改

.opacity(model.isSignedIn ? 1 : 0)

.opacity(self.isSignedIn ? 1 : 0)
,

您可以直接在withAnimation内部指定动画。这样,它将仅针对此更改:

Button(action: {
    withAnimation(.easeInOut) { // add animation
        self.model.logout()
    }
}) {
    Text("Sign Out")
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。