Nikola Lajic
Nikola Lajic

Reputation: 4075

SwiftUI stacked property animations ignored when embedded

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.

Upvotes: 1

Views: 335

Answers (3)

Nikola Lajic
Nikola Lajic

Reputation: 4075

After updating to Xcode 11.2.1 this issue was resolved.

Upvotes: 0

Asperi
Asperi

Reputation: 257789

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

Upvotes: 1

E.Coms
E.Coms

Reputation: 11531

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)
}

Upvotes: 0

Related Questions