0

I have 3 Text View in a VStack, and I want the middle one to bounce by using scaleEffect. However, there is some additional unexpected up and down animation.

I found that once I remove the view from NavigationView, it will behave normal.

Is the problem on my side or Apple's side? And how to fix it? Thanks.

// TestingApp.swift

import SwiftUI

@main
struct TestingApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationView {
                LaunchView()
            }
        }
    }
}
// LaunchView.swift

import SwiftUI

struct LaunchView: View {
    var body: some View {
        NavigationLink("To ContentView", destination: ContentView())
    }
}

struct LaunchView_Previews: PreviewProvider {
    static var previews: some View {
        LaunchView()
    }
}
// ContentView.swift

import SwiftUI

struct ContentView: View {
    @State private var scaleFactor: CGFloat = 0.8
    
    var body: some View {
        VStack {
            Text("Text above")
            Text("Text bouncing")
                .scaleEffect(scaleFactor)
                .onAppear {
                    withAnimation(.spring().repeatForever(autoreverses: true)) {
                        scaleFactor = 1
                    }
                }
            Text("Text below")
        }
        .font(.largeTitle)
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
keanehui
  • 185
  • 2
  • 13
  • Additionally, ContentView has no problem in Preview, the problem occurs only in simulator with NavigationView – keanehui Feb 22 '22 at 12:38
  • 1
    While you weren't clear as to the actual unexpected animation, I presume it is the entire view animating in. Try wrapping the animation in `.onAppear` in a `Dispatchqueue.main.asyncAfter(deadline:)` with a small delay. The issue seems to be that the `.onAppear()` fires before the view is actually on screen, and this messes with the view coming on screen. – Yrb Feb 22 '22 at 12:48
  • @Yrb Thank you! Yes this is exactly the solution I was looking for. I found a similar question after I post the question so I answered below for other's reference. – keanehui Feb 22 '22 at 12:51

1 Answers1

1

Refer to SwiftUI: Broken explicit animations in NavigationView.

Editted solution:

// ContentView.swift

struct ContentView: View {
    @State private var scaleFactor: CGFloat = 0.8

    var body: some View {
        VStack {
            Text("Text above")
            Text("Text bouncing")
                .scaleEffect(scaleFactor)
                .onAppear {
                    DispatchQueue.main.asyncAfter(deadline: .now() + DispatchTimeInterval.milliseconds(200)) { // delay for 0.2 seconds
                            withAnimation(.spring().repeatForever(autoreverses: true)) {
                                scaleFactor = 1
                        }
                    }
                }
            Text("Text below")
        }
        .font(.largeTitle)
        .padding()
    }
}

Solution:

// ContentView.swift

struct ContentView: View {
    @State private var scaleFactor: CGFloat = 0.8
    
    var body: some View {
        VStack {
            Text("Text above")
            Text("Text bouncing")
                .scaleEffect(scaleFactor)
                .onAppear {
                    DispatchQueue.main.async {
                        withAnimation(.spring().repeatForever(autoreverses: true)) {
                            scaleFactor = 1
                        }
                    }
                }
            Text("Text below")
        }
        .font(.largeTitle)
        .padding()
    }
}
keanehui
  • 185
  • 2
  • 13