当视图出现在 SwiftUI 中时禁用动画

Adr*_*nco 6 swift swiftui swiftui-list

我在尝试在 SwiftUI 中显示自定义加载视图时遇到问题。我创建了一个自定义结构视图 OrangeActivityIndi​​cator:

struct OrangeActivityIndicator: View {
    var style = StrokeStyle(lineWidth: 6, lineCap: .round)
    @State var animate = false
    let orangeColor = Color.orOrangeColor
    let orangeColorOpaque = Color.orOrangeColor.opacity(0.5)
    
    init(lineWidth: CGFloat = 6) {
        style.lineWidth = lineWidth
    }
    
    var body: some View {
        ZStack {
            Circle()
                .trim(from: 0, to: 0.7)
                .stroke(
                    AngularGradient(gradient: .init(colors: [orangeColor, orangeColorOpaque]), center: .center), style: style
                )
                .rotationEffect(Angle(degrees: animate ? 360 : 0))
                .animation(Animation.linear(duration: 0.7).repeatForever(autoreverses: false))
        }.onAppear() {
            self.animate.toggle()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在不同的屏幕或视图中使用它,我的问题是它看起来很奇怪,例如在应用程序的 CampaignsView 中,当服务器调用正在进行时我会显示它。

struct CampaignsView: View {
    
    @ObservedObject var viewModel: CampaignsViewModel
    
    var body: some View {
        NavigationView {
            ZStack {
                VStack(spacing: 0) {
                    CustomNavigationBar(campaignsNumber: viewModel.cardCampaigns.count)
                        .padding([.leading, .trailing], 24)
                        .frame(height: 25)
                    CarouselView(x: $viewModel.x, screen: viewModel.screen, op: $viewModel.op, count: $viewModel.index, cardCampaigns: $viewModel.cardCampaigns).frame(height: 240)
                    CampaignDescriptionView(idx: viewModel.index, cardCampaigns: viewModel.cardCampaigns)
                        .padding([.leading, .trailing], 24)
                    Spacer()
                }
                .onAppear {
                    self.viewModel.getCombineCampaigns()
                }
                if viewModel.isLoading {
                    OrangeActivityIndicator()
                        .frame(width: 40, height: 40)
                }
            }
            .padding(.top, 34)
            .background(Color.orBackgroundGrayColor.edgesIgnoringSafeArea(.all))
            .navigationBarHidden(true)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

指示器本身正确旋转,问题是当它出现时,它显示为从屏幕底部到中间的平移动画。这是我的 viewModel 与服务器调用和 isLoading 属性:

class CampaignsViewModel: ObservableObject {
    
    @Published var index: Int = 0
    @Published var cardCampaigns: [CardCampaign] =  [CardCampaign]()
    @Published var isLoading: Bool = false

    var cancellable: AnyCancellable?


    
    func getCombineCampaigns() {
        self.isLoading = true
        let campaignLoader = CampaignLoader()
        cancellable = campaignLoader.getCampaigns()
            .receive(on: DispatchQueue.main)
            //Handle Events operator is used for debugging.
            .handleEvents(receiveSubscription: { print("Receive subscription: \($0)") },
                          receiveOutput: { print("Receive output: \($0)") },
                          receiveCompletion: { print("Receive completion: \($0)") },
                          receiveCancel: { print("Receive cancel") },
                          receiveRequest: { print("Receive request: \($0)") })
            .sink { completion in
                switch completion {
                case .finished:
                    break
                case .failure(let error):
                    print(error)
                }
            } receiveValue: { campaignResult in
                self.isLoading = false
                guard let campaignsList = campaignResult.content else {
                    return
                }
                self.cardCampaigns = campaignsList.map { campaign in
                    return CardCampaign(campaign: campaign)
                }
                self.moveToFirstCard()
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 4

使用具有链接相关状态的动画

var body: some View {
    ZStack {
        Circle()
            .trim(from: 0, to: 0.7)
            .stroke(
                AngularGradient(gradient: .init(colors: [orangeColor, orangeColorOpaque]), center: .center), style: style
            )
            .rotationEffect(Angle(degrees: animate ? 360 : 0))
            .animation(Animation.linear(duration: 0.7)
                                .repeatForever(autoreverses: false), 
                       value: animate)                              // << here !!
    }.onAppear() {
        self.animate.toggle()
    }
}
Run Code Online (Sandbox Code Playgroud)