我一直在测试基于SwiftUI-labs的转换是如何工作的,但我发现转换不应该都以相同的方式实现。基于上一篇文章:
请注意,从 XCode 11.2 开始,过渡不再适用于隐式动画
事情是,我发现了一些奇怪的东西。使用隐式动画或将动画与其关联时,某些过渡效果很好。那么,应该使用什么动画呢?这得看情况。什么?我不知道。我希望任何人都可以帮助我解释这一切。
在下面的测试中,我创建了 5 个视图,每个视图都与不同的转换相关联:.opacity
、.scale
、.move
、.slide
和combined
(.opacity
和.move
)。以下是我的发现:
注意:我使用的是 XCODE 11.4 和模拟器!
使用隐式动画的过渡
只有.move
和.slide
转换工作正常(删除和插入)。
使用显式动画的过渡
移除和插入动画适用于所有过渡。
将动画与每个过渡相关联
只有.scale
和.opacity
转换工作正常(删除和插入)。
从我的角度来看,没有实现转换的标准方法会使事情变得复杂,而且在组合转换时(.combined
)。
我错过了一些关于实施的东西吗?这是我的代码:
struct TestAnimation: View {
@State var show : Bool = true
var colors : [Color] = [.orange, .yellow, .green, .blue, .pink]
var body: some View {
VStack(alignment: .leading) {
Spacer()
Color.purple
.frame(height: 100)
.overlay(
Text("Tap Me!").foregroundColor(.white))
.onTapGesture {
// (#1) implicit animation
self.show.toggle()
// (#2) explicit animation
/*withAnimation(Animation.easeInOut(duration: 1)) {
self.show.toggle()
}*/
// (#3) associate an animation with a transition
//self.show.toggle()
}
HStack {
if show {
Rectangle()
.fill(colors[0])
.frame(width: 70, height: 100)
.overlay(Text("opacity"))
.transition(AnyTransition.opacity) // (#1) - doesn't animate, only removes/inserts the view
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.opacity) // (#2) - only animates the removal, not the insertion
//.transition(AnyTransition.opacity.animation(.easeInOut(duration: 1))) // (#3) - animates removal and insertion
Rectangle()
.fill(colors[1])
.frame(width: 70, height: 100)
.overlay(Text("scale"))
.transition(AnyTransition.scale) // (#1) - doesn't animate, only removes/inserts the view
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.scale) // (#2) - only animates the removal, not the insertion
//.transition(AnyTransition.scale.animation(.easeInOut(duration: 1))) // (#3) - animates removal and insertion
Rectangle()
.fill(colors[2])
.frame(width: 70, height: 100)
.overlay(Text("move"))
.transition(AnyTransition.move(edge: .bottom)) // (#1) - animates removal and insertion
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.move(edge: .bottom)) // (#2) - only animates the removal, not the insertion
//.transition(AnyTransition.move(edge: .bottom).animation(.easeInOut(duration: 1))) // (#3) - doesn't animate, only removes/inserts the view
Rectangle()
.fill(colors[3])
.frame(width: 70, height: 100)
.overlay(Text("slide"))
.transition(AnyTransition.slide) // (#1) - animates removal and insertion
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.slide) // (#2) - only animates the removal, not the insertion
//.transition(AnyTransition.slide.animation(.easeInOut(duration: 1))) // (#3) - doesn't animate, only removes/inserts the view
Rectangle()
.fill(colors[4])
.frame(width: 70, height: 100)
.overlay(Text("op&mv"))
.transition(AnyTransition.opacity.combined(with: .move(edge: .bottom))) // (#1) - doesn't animate, only removes/inserts the view
.animation(.easeInOut(duration: 1)) // (#1)
//.transition(AnyTransition.opacity.combined(with: .move(edge: .bottom))) // (#2) - only animates removal, not the insertion
//.transition(AnyTransition.opacity.combined(with: .move(edge: .bottom)).animation(.easeInOut(duration: 1))) // (#3) - animates removal (it's not smooth), and only animates opacity on insertion
}
}
.frame(height: 100)
.padding(7)
.border(Color.gray)
}
}
}