SwiftUI Button unintended animation during transition

Hello, I see unintended animation applied to my Button that makes it "jump out" of view hierarchy, please help me to understand what happens and why.

I have button with style and transition applied to it. On showButton change I expect my view with button to disappear with slide animation with duration of 1 second. And this happens indeed, but the button itself animates separately from its parent view, it jumps out of parent view that is definitely not expected.

struct ButtonAnimationTest: View {
  @State var showButton: Bool = true

  var body: some View {
    VStack {
      if showButton {
        Button("makeTransition") {
          showButton = false
        }
        .buttonStyle(MyButtonStyle())
        .padding()
        .background(Color.black)
        .transition(.slide)
      }
    }
    .animation(.easeIn(duration: 1), value: showButton)
  }
}


struct MyButtonStyle: ButtonStyle {
  func makeBody(configuration: Configuration) -> some View {
    configuration.label
      .foregroundColor(.white)
      .background(.green)
      .scaleEffect(configuration.isPressed ? 0.5 : 1)
      .animation(.linear(duration: 0.1), value: configuration.isPressed)
  }
}

My guess this happens because button has it's own internal animation that overrides animation from parent view. So to disable it I added

.transaction { $0.disablesAnimations = true }

to the button, to disable all animations happens inside. And this works, it disables unneeded animation during transition, but it also disables my scale animation from ButtonStyle, that is not expected.

Please help me to understand how animation management works and how disable only some animations (and why button animation during transition appears?)

Answered by swiftuiforever in 752934022

Try this

struct ButtonAnimationTest: View {
  @State var showButton: Bool = true

  var body: some View {
    VStack {
      if showButton {
        Button("makeTransition") {
            withAnimation {
                showButton.toggle()
            }
        }
        .buttonStyle(MyButtonStyle())
        .padding()
        .background(Color.black)
        .transition(.slide)
      }
    }
    .animation(.easeIn(duration: 1), value: showButton)
  }
}
Accepted Answer

Try this

struct ButtonAnimationTest: View {
  @State var showButton: Bool = true

  var body: some View {
    VStack {
      if showButton {
        Button("makeTransition") {
            withAnimation {
                showButton.toggle()
            }
        }
        .buttonStyle(MyButtonStyle())
        .padding()
        .background(Color.black)
        .transition(.slide)
      }
    }
    .animation(.easeIn(duration: 1), value: showButton)
  }
}
SwiftUI Button unintended animation during transition
 
 
Q