我正在尝试使用SwiftUI在两种状态之间转换。
我已将其简化为一个简单的示例
struct Test2View: View {
@State var isLoading: Bool = true
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 10)
.fill(Color. secondary)
.shadow(radius: 4, x: 2, y: 5)
.frame(width: 300, height: 150, alignment: .center)
if isLoading {
Text("Loading")
.transition(.moveAndFade())
} else {
Text("Content")
.transition(.moveAndFade())
}
}.onTapGesture {
withAnimation {
self.isLoading.toggle()
}
}
}
}
extension AnyTransition {
static func moveAndFade(delay: TimeInterval = 0) -> AnyTransition {
let insertion = AnyTransition.offset(x: 0, y: 15)
.combined(with: .opacity)
let removal = AnyTransition.offset(x: 20, y: 20)
.combined(with: .opacity)
return .asymmetric(insertion: insertion, removal: removal)
}
}
这可以满足我在没有RoundedRectangle的情况下的预期方式:
但是,一旦添加RoundRectangle,我就会丢失删除动画(除非我中断了动画,否则您可以看到我期望的动画):
有人知道为什么RoundedRectangle与动画混淆吗?我什至尝试添加.transition(.identity)
都没有成功。
答案 0 :(得分:0)
我不能说出动画改变的确切原因,但是我找到了原因。这与框架的大小有关。
您的Test2View
版本的视图主体:
ZStack {
RoundedRectangle(cornerRadius: 10)
.fill(Color.white)
.shadow(radius: 4, x: 2, y: 5)
.frame(width: 300, height: 150, alignment: .center)
if isLoading {
Text("Loading")
.transition(.moveAndFade())
} else {
Text("Content")
.transition(.moveAndFade())
}
}
.border(Color.red)
.onTapGesture {
withAnimation {
self.isLoading.toggle()
}
}
固定版本:
ZStack {
if isLoading {
Text("Loading")
.transition(.moveAndFade())
} else {
Text("Content")
.transition(.moveAndFade())
}
}
.background(
RoundedRectangle(cornerRadius: 10)
.fill(Color.white)
.shadow(radius: 4, x: 2, y: 5)
.frame(width: 300, height: 150, alignment: .center)
)
.border(Color.green)
.onTapGesture {
withAnimation {
self.isLoading.toggle()
}
}
基本上,我使用.background
而不是创建VStack
。
比较图像:
边框颜色仅用于指示帧大小。您可以删除它!