我想在 SwiftUI 中创建一个 View ,它可以动态添加一个带有动画的 subview 。
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"))
}
}
}
}
上面的代码可以很好地处理动画。然而,当我将 View 选择部分移动到一个函数中时,动画不再起作用(因为我想动态添加不同的 View ,因此,我将逻辑放在一个函数中。)
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")
}
}
}
}
注意两点:
- 你上面的两个例子是不同的,这就是你得到不同结果的原因。第一个应用过渡和动画到 DetailView,然后用 AnyView 类型删除它。第二种类型 - 使用 AnyView 删除 DetailView,然后应用过渡和动画。
- 与其使用 AnyView 和类型删除,我更喜欢将条件逻辑封装在
Group
中看法。那么你返回的类型就是Group
,这将正确地动画。 - 如果您想为 subview 的两种可能性设置不同的动画,您现在可以将它们直接应用于
DetailView()
。或Text("test")
.
更新
Group
方法仅适用于 if
, elseif
, 和 else
声明。如果要使用开关,则必须将每个分支包装在 AnyView()
中.但是,这会破坏过渡/动画。使用 switch
和目前无法设置自定义动画。
关于ios - SwiftUI 动态添加 subview 但动画不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58160011/