3

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.

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?

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
          }
        }
    }
  }
}
James Allardice
  • 164,175
  • 21
  • 332
  • 312

2 Answers2

3

Probably you wanted transition, something like

demo

Update: re-tested with 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)
        }
    }
}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Well done! :) However, about the question, strictly, that's too bad this is still not available natively in SwiftUI in 2021. – Moose Jan 21 '21 at 18:57
  • Also as a follow up question... what is the benefit of using a binding in the sub-view? It appears to work either way. – James Allardice Jan 23 '21 at 11:21
1

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?

Moose
  • 2,607
  • 24
  • 23