I have a SwiftUI View
which has a custom animation that runs onAppear
. I am trying to get the view to animate onDisappear
too but it just immediately vanishes.
我有一个SwiftUI视图,它有一个在外观上运行的自定义动画。我也试着让它的视点变成动画,但它马上就消失了。
The below example reproduces the problem - the MyText
view should slide in from the left and slide out to the right. The id
modifier is used to ensure a new view is rendered each time the value changes, and I have confirmed that both onAppear
and onDisappear
are indeed called each time, but the animation onDisappear
never visibly runs. How can I achieve this?
下面的示例再现了这个问题-MyText视图应该从左侧滑入,然后滑出到右侧。Id修饰符用于确保每次值更改时都会呈现一个新的视图,并且我已经确认,每次确实都会调用onOuar和onDis现,但动画onDisshow从不会明显地运行。我怎样才能做到这一点呢?
struct Survey: View {
@State private var id = 0
var body: some View {
VStack {
MyText(text: "\(id)").id(id)
Button("Increment") {
self.id += 1
}
}
}
struct MyText: View {
@State private var offset: CGFloat = -100
let text: String
var body: some View {
return Text(text)
.offset(x: offset)
.onAppear() {
withAnimation(.easeInOut(duration: 2)) {
self.offset = 0
}
}
.onDisappear() {
withAnimation(.easeInOut(duration: 2)) {
self.offset = 100
}
}
}
}
}
更多回答
优秀答案推荐
Probably you wanted transition, something like
可能你想要过渡,就像
Update: re-tested with Xcode 13.4 / iOS 15.5
更新:使用Xcode 13.4/iOS 15.5重新测试
struct Survey: View {
@State private var id = 0
var body: some View {
VStack {
MyText(text: "\(id)")
Button("Increment") {
self.id += 1
}
}
}
struct MyText: View {
var text: String
var body: some View {
Text("\(text)").id(text)
.frame(maxWidth: .infinity)
.transition(.slide)
.animation(.easeInOut(duration: 2), value: text)
}
}
}
I'm afraid it can't work since the .onDisappear modifier is called once the view is hidden.
However there is a nice answer here :
Is there a SwiftUI equivalent for viewWillDisappear(_:) or detect when a view is about to be removed?
我担心它不能工作,因为一旦隐藏了视图,就会调用.onDis现修饰符。然而,这里有一个很好的答案:是否有一个SwiftUI等同于viewWillDis现(_:)或检测何时要删除一个视图?
maybe sth. like that
也许是某样东西。就像这样
func disappearAnimation() {
withAnimation(.easeInOut(duration: animationDuration)) {
// animation
}
DispatchQueue.main.asyncAfter(deadline: .now() + animationDuration) {
dismiss()
}
}
更多回答
Well done! :) However, about the question, strictly, that's too bad this is still not available natively in SwiftUI in 2021.
做得好!:)然而,关于这个问题,严格来说,这太糟糕了,2021年SwiftUI仍然不能本地提供。
Also as a follow up question... what is the benefit of using a binding in the sub-view? It appears to work either way.
还有一个后续问题..。在子视图中使用绑定有什么好处?无论是哪种方式,它似乎都能奏效。
我是一名优秀的程序员,十分优秀!