[英]SwiftUI add subview dynamically but the animation doesn't work
I would like to create a view in SwiftUI that add a subview dynamically and with animation.我想在 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"))
}
}
}
}
The above code works fine with the animation.上面的代码适用于 animation。 however when i move the view selection part into a function, the animation is not working anymore (since i want to add different views dynamically, therefore, I put the logic in a function.)
但是,当我将视图选择部分移动到 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"))
}
}
}
it looks totally the same to me, however, i don't understand why they have different result.它对我来说看起来完全一样,但是,我不明白为什么它们有不同的结果。 Could somebody explain me why?
有人可以解释一下为什么吗? and any better solutions?
以及任何更好的解决方案? thanks alot!
多谢!
Here's your code, modified so that it works:这是您的代码,经过修改后可以正常工作:
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")
}
}
}
}
Note two things:注意两点:
Group
view.Group
视图中。 Then the type you return is Group
, which will animate properly.Group
,它会正确地动画。DetailView()
or Text("test")
.DetailView()
或Text("test")
。 Update更新
The Group
method will only work with if
, elseif
, and else
statements. Group
方法仅适用于if
、 elseif
和else
语句。 If you want to use a switch, you will have to wrap each branch in AnyView()
.如果要使用开关,则必须将每个分支包装在
AnyView()
中。 However, this breaks transitions/animations.但是,这会破坏过渡/动画。 Using
switch
and setting custom animations is currently not possible.目前无法使用
switch
和设置自定义动画。
I was able to get it to work with a switch statement by wrapping the function that returns an AnyView
in a VStack
.通过包装在 VStack 中返回
AnyView
的VStack
,我能够让它与 switch 语句一起使用。 I also had to give the AnyView
an .id
so SwiftUI can know when it changes.我还必须给
AnyView
一个.id
,以便 SwiftUI 可以知道它何时发生变化。 This is on Xcode 11.3 and iOS 13.3这是在 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))
}
}
}
Also for my example in the ViewModel
I need to wrap the viewState
changes in a withAnimation
block同样对于我在
ViewModel
中的示例,我需要将viewState
更改包装在withAnimation
块中
withAnimation {
self.viewState = .loading
}
In iOS 14 they added the possibility to use if let
and switch
statements in function builders.在 iOS 14 中,他们增加了在 function 构建器中使用
if let
和switch
语句的可能性。 Maybe it helps for your issues:也许它对您的问题有帮助:
https://www.hackingwithswift.com/articles/221/whats-new-in-swiftui-for-ios-14 (at the article's bottom) https://www.hackingwithswift.com/articles/221/whats-new-in-swiftui-for-ios-14 (在文章底部)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.