SwiftUI 动画在首次显示时冻结

问题描述 投票:0回答:2

我正在编写我的第一个 SwiftUI 应用程序,我想在文本上创建动画(以缓慢显示和隐藏该文本)。这是我的代码:

import SwiftUI

struct TrendLabel: View {
    let trendType: String
    
    @State private var animationAmount = 0.0
    
    var body: some View {
        HStack {
            if(trendType != "aucune"){
                Label(trendType, systemImage: "arrow.down.right")
                    .foregroundColor(trendType == "hausse" ? .red : .green)
                    .opacity(2 - animationAmount)
                    .animation(
                        .easeOut(duration: 1).delay(1).repeatForever(autoreverses: true),
                        value: animationAmount
                    )
            }
        }
        .onAppear {
            animationAmount = 1.6
        }
    }
}

struct TrendLabel_Previews: PreviewProvider {
    static var previews: some View {
        TrendLabel(trendType: "hausse")
    }
}

但它似乎不起作用,因为我的文本被冻结为最小不透明度值(here is a screenshot of the result)。

有人知道如何解决这个问题吗?

swift animation swiftui
2个回答
1
投票

欢迎来到 StackOverflow!您的动画存在一些问题。

  1. 要设置不透明度动画,您需要一个
    Bool
    值,或者可以计算为
    Bool
    值的表达式。然后您使用三元来做出决定。
  2. .opacity()
    值必须介于 0 和 1 之间。

您的代码应该是:

struct TrendLabel: View {
    let trendType: String
    
    @State private var animate = false
    @State private var animationAmount = 0.0
    
    var body: some View {
        HStack {
            if(trendType != "aucune"){
                Label(trendType, systemImage: "arrow.down.right")
                    .foregroundColor(trendType == "hausse" ? .red : .green)
                    .opacity(animate ? animationAmount : 1)
                    .animation(
                        .easeOut(duration: 1).delay(1).repeatForever(autoreverses: true),
                        value: animate
                    )
            }
        }
        .onAppear {
            animationAmount = 0.4
            animate = true
        }
    }
}

0
投票

基于@Yrb的答案,您可以创建一个修饰符:

struct DelayedAppear: ViewModifier {
    
    let delay: TimeInterval
    let callback: () -> Void
    
    func body(content: Content) -> some View {
        content
            .onAppear {
                DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                    callback()
                }
            }
    }
}

extension View {
    func onAppear(after: TimeInterval, perform: @escaping () -> Void) -> some View {
        modifier(DelayedAppear(delay: after, callback: perform))
    }
}

用途:

HStack {
 ...            
}
.onAppear(after: 0.5) {
    animationAmount = 0.4
    animate = true
}
© www.soinside.com 2019 - 2024. All rights reserved.