1

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
  • 160,885
  • 21
  • 326
  • 309

2 Answers2

2

Probably you wanted transition, something like

demo

struct Survey: View {
  @State private var id = 0

  var body: some View {
    VStack {
      MyText(text: $id)

      Button("Increment") {
        self.id += 1
      }
    }
  }

  struct MyText: View {
    @Binding var text: Int
    

    var body: some View {
      return Text("\(text)").id(text)
            .frame(maxWidth: .infinity)
            .transition(.slide)
            .animation(.easeInOut(duration: 2))
    }
  }
}
Asperi
  • 173,274
  • 14
  • 284
  • 455
  • 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
0

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,444
  • 22
  • 23