iOS 14 中引入了 matchedGeometryEffect() 修饰符,允许视图进行变形动画。你只需要会绘制原视图和最终要转换到的视图,matchedGeometryEffect 就会自动计算二者之间的差异并创建出转换动画:
struct ContentView: View {
@Namespace private var shapeTransition // 1
@State var expand = false // 2
var body: some View {
if expand {
Circle()
.fill(Color.green)
.matchedGeometryEffect(id: "circle", in: shapeTransition) // 3
.frame(width: 300, height: 300)
.offset(y: -200)
.animation(.default)
.onTapGesture { // 4
self.expand.toggle()
}
} else {
Circle()
.fill(Color.green)
.matchedGeometryEffect(id: "circle", in: shapeTransition) // 5
.frame(width: 150, height: 150)
.offset(y: 0)
.animation(.default)
.onTapGesture { // 6
self.expand.toggle()
}
}
}
}
- 定义一个命名空间,一个命名空间是一个名字(ID),用于区分不同的动画,位于同一个命名空间(shapeTransition)内的对象,将受此动画的影响。
- 视图状态 expand,用于切换 Circle 视图的不同状态,expand 为 true 绘制加大的圆,expand 为 false 绘制较小的圆。大小圆之间来回切换。
- matchedGeometryEffect(id:, in:) 将此视图标记为变形动画 shapeTransition 之内的对象,对象 id 为 circle。
- 点击时切换到另一状态。
- 虽然前面已经标记过一次 matchedGeometryEffect,但这里仍然需要标记一次,因为任一状态下绘制的是完全不同的 Circle 视图,它们不可能并存。
- 点击时切换到另一状态。
matchedGeometryEffect 确实很方便,然而只有 iOS 14 以上才支持。