Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spinner animation starts bouncing once the view is updated

Tags:

swiftui

I have an image that I apply a 360 rotation on to have the effect of loading/spinning. It works fine until I add Text underneath, the image still spins but it bounces vertically.

Here is code to see it:

import SwiftUI

@main
struct SpinnerApp: App {    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    @State var isAnimating = false
    @State var text = ""
    
    var animation: Animation {
        Animation.linear(duration: 3.0)
            .repeatForever(autoreverses: false)
    }

    var body: some View {
        HStack {
            Spacer()
            VStack {
                Circle()
                    .foregroundColor(Color.orange)
                    .frame(height: 100)
                    .rotationEffect(Angle(degrees: self.isAnimating ? 360 : 0.0))
                    .animation(self.isAnimating ? animation : .default)
                    .onAppear { self.isAnimating = true }
                    .onDisappear { self.isAnimating = false }
                if self.text != "" {
                    Text(self.text)
                }
            }
            Spacer()
        }
        .background(Color.gray)
        .onAppear(perform: {
            DispatchQueue.main.asyncAfter(deadline: .now()+4, execute: {
                self.text = "Test"
            })
        })
    }
}

I replaced the image with a Circle so you won't be able to see the spinning/animation, but you can see the circle bouncing vertically once we set the text. If the text was there from the beginning and it didn't change then all is fine. The issue only happens if the text is added later or if it got updated at some point.

Is there a way to fix this?

like image 403
mota Avatar asked Oct 20 '25 22:10

mota


1 Answers

Try using explicit animations instead, with withAnimation. When you use .animation(), SwiftUI sometimes tries to animate the position of your views too.

struct ContentView: View {
    @State var isAnimating = false
    @State var text = ""
    
    var animation: Animation {
        Animation.linear(duration: 3.0)
            .repeatForever(autoreverses: false)
    }

    var body: some View {
        HStack {
            Spacer()
            VStack {
                Circle()
                    .foregroundColor(Color.orange)
                    .overlay(Image(systemName: "plus")) /// to see the rotation animation
                    .frame(height: 100)
                    .rotationEffect(Angle(degrees: self.isAnimating ? 360 : 0.0))
                    .onAppear {
                        withAnimation(animation) { /// here!
                            self.isAnimating = true
                        }
                    }
                    .onDisappear { self.isAnimating = false }
                
                if self.text != "" {
                    Text(self.text)
                }
            }
            Spacer()
        }
        .background(Color.gray)
        .onAppear(perform: {
            DispatchQueue.main.asyncAfter(deadline: .now()+4, execute: {
                self.text = "Test"
            })
        })
    }
}

Result:

Circle continues spinning even after text is added
like image 106
aheze Avatar answered Oct 24 '25 11:10

aheze



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!