1
votes

Going by examples we can see that it is possible to animate different properties with different animations. For example:

Button("Tap me") {self.isShowingRed.toggle()}
    .frame(width: 200, height: 200)
    .background(isShowingRed ? Color.red : Color.blue)
    .animation(.easeIn(duration: 2.5))
    .clipShape(RoundedRectangle(cornerRadius: isShowingRed ? 50 : 0))
    .animation(Animation.easeInOut(duration: 0.1).repeatCount(5))

This code will animate the button background from red to blue in 2.5 seconds, while animating the corner radius from 0 to 50 with 5 repetitions.

The problem appears as soon as the view is embedded:

VStack {
    Button("Tap me") {self.isShowingRed.toggle()}
        .frame(width: 200, height: 200)
        .background(isShowingRed ? Color.red : Color.blue)
        .animation(.easeIn(duration: 2.5))
        .clipShape(RoundedRectangle(cornerRadius: isShowingRed ? 50 : 0))
        .animation(Animation.easeInOut(duration: 0.1).repeatCount(5))
    } 
}

When the button is embedded only the first animation is used, in this case both the color and the radius will be animated in 2.5 seconds with no repetitions.

Even if I make the button a separate component, the same problem persists.

Am I doing something wrong or is this a SwiftUI bug?

Edit: I'm using Xcode 11.1 and testing on the simulator.

3
at xCode 11.2 it seems that nothing changes and doesn't matter is button embed in VStack or notАлександр Грабовский

3 Answers

1
votes

As I observed when something unexpected happens when there is .background, then issue is in it... In your use-case the animation must be applied to background content and this solves the problem.

Here is example I used and it animates as you wanted with and w/o container.

import SwiftUI

struct TestButtonAnimation: View {
    @State private var isShowingRed = false
    var body: some View {
        VStack {
            Button("Tap me") {self.isShowingRed.toggle()}
                .frame(width: 200, height: 200)
                .background(
                    Group {isShowingRed ? Color.red : Color.blue}
                    .animation(.easeIn(duration: 2.5))
                )
                .clipShape(RoundedRectangle(cornerRadius: isShowingRed ? 50 : 0))
                .animation(Animation.easeInOut(duration: 0.1).repeatCount(5))
        }
    }
}

struct TestButtonAnimation_Previews: PreviewProvider {
    static var previews: some View {
        TestButtonAnimation()
    }
}

Tested with: Xcode 11.1

0
votes

You may try this way .animation(.default) in the container

  var body: some View {
  VStack{
  Button("Tap me") {self.isShowingRed.toggle()}
 .frame(width: 200, height: 200)
 .background(isShowingRed ? Color.red : Color.blue)
 .animation(.easeIn(duration: 2.5))
.clipShape(RoundedRectangle(cornerRadius: isShowingRed ? 50 : 0))
.animation(Animation.easeInOut(duration: 0.1).repeatCount(5))
}.animation(.default)
}
0
votes

After updating to Xcode 11.2.1 this issue was resolved.