mightknow
mightknow

Reputation: 276

Why does my SwiftUI animation revert to the previous frame on rotation?

I have a SwiftUI View that is meant to be sort of a "warning" background that flashes on and off. It appears inside another View with a size that changes depending on device orientation. Everything works properly upon the first appearance, but if the device is rotated while the warning view is active it incorporates the frame of the previous orientation into the animation, making it not only flash on and off, but also move in and out of the view its positioned in, as well as change to and from the size it was on the previous orientation. Why is this happening and how can I fix it? Generic code:

struct PulsatingWarningBackground: View {
    let color : Color
    let speed : Double
    @State private var opacity : Double = 1
    var body: some View {
        GeometryReader {geometry in
            self.color
            .opacity(self.opacity)
            .animation(
            Animation
                .linear(duration: self.speed)
                .repeatForever(autoreverses: true)
            )
            .onAppear(perform: {self.opacity = 0})
        }
    }
}

struct PulsatingWarningViewHolder: View {
    var body: some View {
        GeometryReader {geometry in
            ZStack {
                Color.white
                ZStack {
                    Color.black
                    PulsatingWarningBackground(color: .red, speed: 1/4)
                }.frame(width: geometry.frame(in: .local).width/5, height: geometry.frame(in: .local).height/10, alignment: .center)
            }
        }
    }
}

Upvotes: 2

Views: 537

Answers (1)

Aye Chan
Aye Chan

Reputation: 1427

You can apply animation only to opacity by using withAnimation(_:_:) inside onAppear(perform:). It works properly as you want.

struct PulsatingWarningBackground: View {
    let color : Color
    let speed : Double
    @State private var opacity : Double = 1
    var body: some View {
        self.color
        .opacity(self.opacity)
        .onAppear(perform: {
            withAnimation(Animation.linear(duration: self.speed).repeatForever()) {
                self.opacity = 0
            }
        })
    }
}

struct PulsatingWarningViewHolder: View {
    var body: some View {
        GeometryReader {geometry in
            ZStack {
                Color.white
                ZStack {
                    Color.black
                    PulsatingWarningBackground(color: .red, speed: 1/4)
                }
                .frame(width: geometry.frame(in: .local).width/5, height: geometry.frame(in: .local).height/10, alignment: .center)
            }
        }
    }
}

Upvotes: 4

Related Questions