[英]Why does my UIView animation doesn't work after I add a subview to it?
[英]SwiftUI add subview dynamically but the animation doesn't work
我想在 SwiftUI 中创建一个动态添加子视图并使用 animation 的视图。
struct ContentView : View {
@State private var isButtonVisible = false
var body: some View {
VStack {
Toggle(isOn: $isButtonVisible.animation()) {
Text("add view button")
}
if isButtonVisible {
AnyView(DetailView())
.transition(.move(edge: .trailing))
.animation(Animation.linear(duration: 2))
}else{
AnyView(Text("test"))
}
}
}
}
上面的代码适用于 animation。 但是,当我将视图选择部分移动到 function 中时,animation 不再工作(因为我想动态添加不同的视图,因此,我将逻辑放在 ZC1C425268E68385D14AB5074C17A9 中)。
struct ContentView : View {
@State private var isButtonVisible = false
var body: some View {
VStack {
Toggle(isOn: $isButtonVisible.animation()) {
Text("add view button")
}
subView().transition(.move(edge: .trailing))
.animation(Animation.linear(duration: 2))
}
func subView() -> some View {
if isButtonVisible {
return AnyView(DetailView())
}else{
return AnyView(Text("test"))
}
}
}
它对我来说看起来完全一样,但是,我不明白为什么它们有不同的结果。 有人可以解释一下为什么吗? 以及任何更好的解决方案? 多谢!
这是您的代码,经过修改后可以正常工作:
struct ContentView : View {
@State private var isButtonVisible = false
var body: some View {
VStack {
Toggle(isOn: $isButtonVisible.animation()) {
Text("add view button")
}
subView()
.transition(.move(edge: .trailing))
.animation(Animation.linear(duration: 2))
}
}
func subView() -> some View {
Group {
if isButtonVisible {
DetailView()
} else {
Text("test")
}
}
}
}
注意两点:
Group
视图中。 然后你返回的类型是Group
,它会正确地动画。DetailView()
或Text("test")
。更新
Group
方法仅适用于if
、 elseif
和else
语句。 如果要使用开关,则必须将每个分支包装在AnyView()
中。 但是,这会破坏过渡/动画。 目前无法使用switch
和设置自定义动画。
通过包装在 VStack 中返回AnyView
的VStack
,我能够让它与 switch 语句一起使用。 我还必须给AnyView
一个.id
,以便 SwiftUI 可以知道它何时发生变化。 这是在 Xcode 11.3 和 iOS 13.3 上
struct EnumView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
VStack {
view(for: viewModel.viewState)
.id(viewModel.viewState)
.transition(.opacity)
}
}
func view(for viewState: ViewModel.ViewState) -> AnyView {
switch viewState {
case .loading:
return AnyView(LoadingStateView(viewModel: self.viewModel))
case .dataLoaded:
return AnyView(LoadedStateView(viewModel: self.viewModel))
case let .error(error):
return AnyView(ErrorView(error: error, viewModel: viewModel))
}
}
}
同样对于我在ViewModel
中的示例,我需要将viewState
更改包装在withAnimation
块中
withAnimation {
self.viewState = .loading
}
在 iOS 14 中,他们增加了在 function 构建器中使用if let
和switch
语句的可能性。 也许它对您的问题有帮助:
https://www.hackingwithswift.com/articles/221/whats-new-in-swiftui-for-ios-14 (在文章底部)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.