Tested on Xcode 11.3.1 and 11.4:
When attaching implicit animations to a transition, some transition types appear to be broken. Specifically, any position-related transitions do not apply the given implicit animation. .slide, .move, .offset are broken. .opacity and .scale seem ok. (See attachment)
Explicit animations seem to work fine in all cases.
Even with custom compound Transitions, the position-related sub-transitions do not respond to implicit animation.
Is this a bug, or expected behavior?
Seems like this would be a problem if you want to trigger multiple different animation curves for specific UI elements based on an implicit property change.
struct MyExample: View {
@State private var isShowing = true
private let myAnimation = Animation.spring(response: 0.8, dampingFraction: 0.2, blendDuration: 3.0)
var body: some View {
VStack(spacing:20) {
if self.isShowing {
Text("Opacity").modifier(MyBigFont())
.transition(AnyTransition.opacity.animation(myAnimation))
Text("Scale").modifier(MyBigFont())
.transition(AnyTransition.scale.animation(myAnimation))
Text("Slide").modifier(MyBigFont())
.transition(AnyTransition.slide.animation(myAnimation))
Text("Move").modifier(MyBigFont())
.transition(AnyTransition.move(edge: .trailing).animation(myAnimation))
Text("Offset").modifier(MyBigFont())
.transition(AnyTransition.offset(x: 20, y: 0).animation(myAnimation))
Text("Custom").modifier(MyBigFont())
.transition(AnyTransition.myCustomTransition.animation(myAnimation))
}
Spacer()
Button(action: {
self.isShowing.toggle()
}) {
Text("Implicit Toggle")
}
Button(action: {
withAnimation(self.myAnimation) {
self.isShowing.toggle()
}
}) {
Text("Explicit Toggle")
}
}
}
}
struct MyBigFont: ViewModifier {
func body(content: Content) -> some View {
content
.lineLimit(1)
.padding()
.background(Color.purple)
.foregroundColor(.white)
.cornerRadius(8)
.font(Font.system(size: 21).bold())
}
}
struct MyCustomTransition: ViewModifier {
var isEnabled: Bool
func body(content: Content) -> some View {
if isEnabled {
return content
.offset(x: 20.0, y: 0.0)
.opacity(0)
} else {
return content
.offset(x: 0.0, y: 0.0)
.opacity(1)
}
}
}
extension AnyTransition {
static let myCustomTransition = AnyTransition.modifier(
active: MyCustomTransition(isEnabled: true),
identity: MyCustomTransition(isEnabled: false))
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
VStack {
MyExample()
Spacer()
}
}
}

