在 SwiftUI 中同时对按钮的文本和位置进行动画处理

Mis*_*cha 2 animation button swiftui swiftui-animation

我有一个非常简单的视图,仅显示 a Text、 aShape和 aButton垂直堆叠在 a 中ScrollView。是Shapea且仅当是Capsule时才会有条件地显示。showCapsuletrue

\n
struct ContentView: View {\n\n    @State var showCapsule = true\n\n    var body: some View {\n        ScrollView {\n            VStack(spacing: 16) {\n                Text("Why, oh why? ")\n                    .font(.headline)\n                if showCapsule {\n                    Capsule()\n                        .frame(maxWidth: .infinity)\n                        .frame(height: 100)\n                        .foregroundColor(.blue)\n                }\n                Button {\n                    showCapsule.toggle()\n                } label: {\n                    Text(showCapsule ? "Hide" : "Show")\n                }\n                .buttonStyle(.bordered)\n            }\n            .frame(maxWidth: .infinity)\n            .padding()\n        }\n        .animation(.default, value: showCapsule)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

观察到的和预期的动画

\n

我想要动画 的出现和消失Capsule,但结果完全不是我想要的。当胶囊淡出时(这没关系),按钮同时以两种不同的方式进行动画处理:

\n
    \n
  1. 它的背景形状(灰色圆角矩形)从旧位置移动到新位置。
  2. \n
  3. 其文本在旧位置淡出并在新位置淡入。
  4. \n
\n

观察动画

\n

当然,(2)不是我想要的。相反,我希望按钮作为一个整体移动:整个按钮应该从旧位置移动到新位置,而其中的文本则褪色。

\n

更广阔的前景

\n

这是一个更广泛问题的最小示例:如何对语义上相同但值不同的视图进行动画更改?

\n

Button初始化程序中,我使用三元运算符有条件地将不同的字符串传递给其Text标签:

\n
Button {\n    showCapsule.toggle()\n} label: {\n    Text(showCapsule ? "Hide" : "Show")\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Text("Hide")是一个与 不同的值Text("Show"),所以我猜这就是为什么 SwiftUI 无法识别它们并且不“理解”它应该将它们设置为动画的原因。我在带有常量的自定义视图中观察到相同的行为let。有没有办法让 SwiftUI 将此类视图 \xe2\x80\x93 尤其是这个Button\xe2\x80\x93 视为一个单元并正确地对它们进行动画处理?

\n

笔记

\n

我不是寻找像使用两个Text字段(或Buttons)并通过相应设置其不透明度来显示/隐藏它们的解决方法。而是为此类问题寻找解决身份问题的通用解决方案,而不是修补其症状。

\n

Ash*_*lls 6

.drawingGroup您可以通过向按钮添加修饰符来解决此问题:

Button(showCapsule ? "Hide" : "Show") {
    showCapsule.toggle()
}
.drawingGroup()
.buttonStyle(.bordered)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

或者,您可以有两个显示和隐藏的按钮:

ZStack {
    Button("Hide") {
        showCapsule.toggle()
    }
    .buttonStyle(.bordered)
    .opacity(showCapsule ? 1 : 0)

    Button("Show in a very long button") {
        showCapsule.toggle()
    }
    .buttonStyle(.bordered)
    .opacity(showCapsule ? 0 : 1)
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述