Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animated dots relocate after device rotation

I've created a button with three animating dots using SwiftUI. When the screen geometry changes somehow (device rotation, keyboard open, etc.) the animation gets messed up. See the attached video. How can I get the circles to stay in their position relative to the button?

enter image description here

This is my code:

struct ContentView: View {
    var body: some View {
        
        Button(action: {}, label: {
            AnimatedDot().frame(minWidth: 200, maxWidth: .infinity, minHeight: 20, maxHeight: 20)
        }).foregroundColor(Color.blue)
        .padding()
        .background(Color.gray)
        .cornerRadius(10.0)
        .frame(minWidth: 0, maxWidth: 350)
        
    }
}

struct AnimatedDot: View {
    
    @State private var shouldAnimate = false
    
    var body: some View {
        HStack {
            Circle()
                .fill(Color.white)
                .frame(width: 15, height: 15)
                .scaleEffect(shouldAnimate ? 1.0 : 0.5)
                .animation(Animation.easeInOut(duration: 0.3).repeatForever())
            Circle()
                .fill(Color.white)
                .frame(width: 15, height: 15)
                .scaleEffect(shouldAnimate ? 1.0 : 0.5)
                .animation(Animation.easeInOut(duration: 0.3).repeatForever().delay(0.3))
            Circle()
                .fill(Color.white)
                .frame(width: 15, height: 15)
                .scaleEffect(shouldAnimate ? 1.0 : 0.5)
                .animation(Animation.easeInOut(duration: 0.3).repeatForever().delay(0.6))
        }
        .onAppear {
            self.shouldAnimate = true
        }
    }
    
}
like image 721
Martin Claesson Avatar asked Dec 18 '20 12:12

Martin Claesson


1 Answers

Here is fixed body - join animation to state value.

Tested with Xcode 12.1 / iOS 14.1

demo

var body: some View {
    HStack {
        Circle()
            .fill(Color.white)
            .frame(width: 15, height: 15)
            .scaleEffect(shouldAnimate ? 1.0 : 0.5)
            .animation(Animation.easeInOut(duration: 0.3).repeatForever(), value: shouldAnimate)
        Circle()
            .fill(Color.white)
            .frame(width: 15, height: 15)
            .scaleEffect(shouldAnimate ? 1.0 : 0.5)
            .animation(Animation.easeInOut(duration: 0.3).repeatForever().delay(0.3), value: shouldAnimate)
        Circle()
            .fill(Color.white)
            .frame(width: 15, height: 15)
            .scaleEffect(shouldAnimate ? 1.0 : 0.5)
            .animation(Animation.easeInOut(duration: 0.3).repeatForever().delay(0.6), value: shouldAnimate)
    }
    .onAppear {
        self.shouldAnimate = true
    }
}
like image 121
Asperi Avatar answered Oct 20 '22 11:10

Asperi