不透明度的 SwiftUI 文本动画不起作用

SwiftUI Text animation on opacity does not work

问题很简单:我到底怎样才能让 Text 正确地设置动画?

struct ContentView: View {
    @State var foozle: String = ""

    var body: some View {
        VStack() {
            Spacer()

            Text(self.foozle)
                .frame(maxWidth: .infinity)
                .transition(.opacity)

            Button(action: {
                withAnimation(.easeInOut(duration: 2)) {
                    self.foozle = "uuuuuuuuu"
                }
            }) { Text("ugh") }

            Spacer()
        }.frame(width: 320, height: 240)
    }
}

问题:视图坚持做一些愚蠢的动画,其中文本被新文本替换,但被省略号截断,并且它慢慢地横向扩展直到显示整个新文本。

当然,这不是不透明度动画。这不是框架宽度问题,因为我已经通过绘制边框进行了验证。

这只是 SwiftUI 中的另一个愚蠢错误,我将不得不处理它,并祈祷有人修复它吗?

编辑:好的,感谢@Mac3n,我得到了这个灵感,它工作正常,即使它有点丑陋:

Text(self.foozle)
    .frame(maxWidth: .infinity)
    .opacity(op)

Button(action: {
    withAnimation(.easeOut(duration: 0.3)) {
        self.op = 0

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            self.foozle += "omo"

            withAnimation(.easeIn(duration: 0.3)) {
                self.op = 1
            }
        }
    }

}) {
    Text("ugh")
}

如果您想在不透明度上设置动画,您需要更改文本元素的不透明度值。

代码示例:

@State private var textValue: String = "Sample Data"
@State private var opacity: Double = 1
    var body: some View {
        VStack{
            Text("\(textValue)")
                .opacity(opacity)
            Button("Next") {
                withAnimation(.easeInOut(duration: 0.5), {
                    self.opacity = 0
                })
                self.textValue = "uuuuuuuuuuuuuuu"
                withAnimation(.easeInOut(duration: 1), {
                    self.opacity = 1
                })
            }
        }
    }

Transition 在视图 appeared/disappeared 时有效。在您的用例中没有这样的工作流程。

这里是 hide/unhide 带有不透明度动画的文本的可能方法演示:

struct DemoTextOpacity: View {
    var foozle: String = "uuuuuuuuu"
    @State private var hidden = true

    var body: some View {
        VStack() {
            Spacer()

            Text(self.foozle)
                .frame(maxWidth: .infinity)
                .opacity(hidden ? 0 : 1)

            Button(action: {
                withAnimation(.easeInOut(duration: 2)) {
                    self.hidden.toggle()
                }
            }) { Text("ugh") }

            Spacer()
        }.frame(width: 320, height: 240)
    }
}

问题是 SwiftUI 将文本视图视为同一视图。您可以在视图上使用 .id() 方法来设置它。在这种情况下,我只是将值设置为文本本身的哈希值,因此如果您更改文本,整个视图将被替换。

struct ContentView: View {
    @State var foozle: String = ""

    var body: some View {
        VStack() {
            Spacer()

            Text(self.foozle)
                .id(self.foozle.hashValue)
                .frame(maxWidth: .infinity)
                .transition(.opacity)

            Button(action: {
                withAnimation(.easeInOut(duration: 2)) {
                    self.foozle = "uuuuuuuuu"
                }
            }) { Text("ugh") }

            Spacer()
        }.frame(width: 320, height: 240)
    }
}