SwiftUI - 使用淡入淡出动画更改文本

Posted

技术标签:

【中文标题】SwiftUI - 使用淡入淡出动画更改文本【英文标题】:SwiftUI - Change Text with fade animation 【发布时间】:2020-08-21 21:26:01 【问题描述】:

我想看看我是如何做到的,以便通过淡入和淡出更改文本视图的源代码。

因此,如果我有如下简单视图:

struct TestView: View 
    
    @State var text = "I am a shrubber."
    
    func changeText() 
        text = (text == "I am a shrubber.") ? "My name is Roger the Shrubber." : "I am a shrubber."
    
    
    var body: some View 
        VStack 
            Text(self.text)
            TestButton(label: "Change", action: changeText)
        
    
    

如果我点击按钮,文本会立即改变。

现在,如果我将更改的代码包装在 withAnimation 块中,或者将 .animation 视图修饰符添加到 Text 视图,它只会对帧大小的更改进行动画处理。这不是我要找的:

struct TestView: View 
    
    @State var text = "I am a shrubber."
    
    func changeText() 
        withAnimation 
            text = (text == "I am a shrubber.") ? "My name is Roger the Shrubber." : "I am a shrubber."
        
    
    
    var body: some View 
        VStack 
            Text(self.text)
            TestButton(label: "Change", action: changeText)
        
    
    

当然,我可以通过使用.transition 视图修饰符和单独的文本字段(此答案:https://***.com/a/60984127/5919644)来接近我正在寻找的效果,如下所示:

struct TestView: View 
    
    @State var changed = false
    
    var body: some View 
        VStack 
            if !changed 
                Text("I am a shrubber.")
                    .transition(AnyTransition.opacity.animation(.easeInOut(duration:0.3)))
            
            if changed 
                Text("My name is Roger the Shrubber.")
                    .transition(AnyTransition.opacity.animation(.easeInOut(duration:0.3)))
            
            
            TestButton(label: "Change", action:  self.changed.toggle() )
        
    
    

但这是一种糟糕的模式,并且不适用于任意文本更改。即便如此,淡入和淡出也会同时发生。我想让淡出/淡入顺序发生。

【问题讨论】:

你试过使用动画时长吗?例如'.animation(Animation.easeInOut(duration: 3))' 【参考方案1】:

好的,所以我想我自己找到了处理这个问题的最佳方法:通过绑定的发布者观察更改,然后手动淡出、更改文本和淡出。

视图如下所示:

struct FadingTextView: View 
    
    @Binding var source: String
    var transitionTime: Double
    
    @State private var currentText: String? = nil
    @State private var visible: Bool = false
    private var publisher: AnyPublisher<[String.Element], Never> 
        source
            .publisher
            .collect()
            .eraseToAnyPublisher()
    
    
    init(text: Binding<String>, totalTransitionTime: Double) 
        self._source = text
        self.transitionTime = totalTransitionTime / 3
    
    
    private func update(_: Any) 
        guard currentText != nil else 
            currentText = source
            DispatchQueue.main.asyncAfter(deadline: .now() + (transitionTime)) 
                self.visible = true
            
            return
        
        guard source != currentText else  return 
        self.visible = false
        DispatchQueue.main.asyncAfter(deadline: .now() + (transitionTime)) 
            self.currentText = source
            DispatchQueue.main.asyncAfter(deadline: .now() + (transitionTime)) 
                self.visible = true
            
        
    
    
    var body: some View 
        Text(currentText ?? "")
            .opacity(visible ? 1 : 0)
            .animation(.linear(duration: transitionTime))
            .onReceive(publisher, perform: update(_:))
    
    

然后它可以用于任意文本更改,如下所示:

struct TestView: View 
    
    @State private var text: String = "Alpha"
    
    private var values: [String] = ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel"]
    
    private func updateText() 
        self.text = values.randomElement()!
    
    
    var body: some View 
        VStack 
            FadingTextView(text: $text, totalTransitionTime: 1.0)
            Button("Change", action: updateText).padding()
        
    

看起来像这样:

【讨论】:

以上是关于SwiftUI - 使用淡入淡出动画更改文本的主要内容,如果未能解决你的问题,请参考以下文章

动画淡入/淡出标题按钮不起作用

Android使用淡入/淡出动画更改背景图像

(Swift)淡入淡出标签[重复]

动画文本阴影淡入和淡出

Android - 如何使用交叉淡入淡出动画更改状态栏颜色[重复]

使用淡入淡出动画从布尔[重复]更改背景颜色视图