SwiftUI 自定义视图永远重复动画显示出乎意料

SwiftUI Custom View repeat forever animation show as unexpected

我创建了一个自定义 LoadingView 作为从 Internet 加载对象的指示器。添加到 NavigationView 时,显示如下 enter image description here

我只希望它显示在屏幕中间而不是从左上角移动

这是我的代码

struct LoadingView: View {
    @State private var isLoading = false
    var body: some View {
        Circle()
            .trim(from: 0, to: 0.8)
            .stroke(Color.primaryDota, lineWidth: 5)
            .frame(width: 30, height: 30)
            .rotationEffect(Angle(degrees: isLoading ? 360 : 0))
            .onAppear {
                withAnimation(.linear(duration: 1).repeatForever(autoreverses: false)) {
                    self.isLoading.toggle()
                }
            }
            
    }
}

和我的内容视图

struct ContentView: View {
    var body: some View {
        NavigationView {
            LoadingView()
                .frame(width: 30, height: 30)
        }
    }
}

这看起来像是 NavigationView 的错误:没有它动画效果完全正常。它不会在 iOS15.

中修复

工作解决方案是在字符串动画之前使用 DispatchQueue.main.async 等待一个布局周期:

struct LoadingView: View {
    @State private var isLoading = false
    var body: some View {
        Circle()
            .trim(from: 0, to: 0.8)
            .stroke(Color.red, lineWidth: 5)
            .frame(width: 30, height: 30)
            .rotationEffect(Angle(degrees: isLoading ? 360 : 0))
            .onAppear {
                DispatchQueue.main.async {
                    withAnimation(.linear(duration: 1).repeatForever(autoreverses: false)) {
                        self.isLoading.toggle()
                    }
                }
            }
    }
}

这是 NavigationView 的一个错误,我试图杀死所有可能的动画,但 NavigationView 忽略了我的所有尝试,NavigationView 添加一个内部动画到 children!我们现在能做的就到这里!

struct ContentView: View {
    var body: some View {
        NavigationView {
            LoadingView()
        }
        
    }
}


struct LoadingView: View {
    
    @State private var isLoading: Bool = Bool()
    
    var body: some View {
        
        Circle()
            .trim(from: 0, to: 0.8)
            .stroke(Color.blue, lineWidth: 5.0)
            .frame(width: 30, height: 30)
            .rotationEffect(Angle(degrees: isLoading ? 360 : 0))
            .animation(Animation.linear(duration: 1).repeatForever(autoreverses: false), value: isLoading)
            .onAppear { DispatchQueue.main.async { isLoading.toggle() } }
 
    }
    
}