比方说,我有一个简单的个人资料屏幕,如下所示:
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, 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)
}
.onReceive(self.model.$isSignedIn) { value in
withAnimation(Animation.easeIn) {
self.isSignedIn = value
}
}
}
}
有一些问题(在我看来):
@State
var来处理模型中的更改WithAnimation
块都需要单独的.onReceive
问题是:将WithAnimation
应用于@ObservedObject
是正确的方法,还是有更好的解决方案?
答案 0 :(得分:1)
您的第一种方法可以更改,因此您无需使用其他@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)
答案 1 :(得分:0)
您可以直接在withAnimation
内部指定动画。这样,它将仅针对此更改:
Button(action: {
withAnimation(.easeInOut) { // add animation
self.model.logout()
}
}) {
Text("Sign Out")
}