功能
为任意 View 添加“双指捏合”缩放手势,实时返回缩放比例(relative to 1.0),可跟踪变化或结束时持久化。
参数
onChanged:实时更新 UI,可配合withAnimation(.linear)实现平滑。onEnded:持久化缩放值、重置反弹(示例用withAnimation(.spring())回弹到原尺寸)。- 若仅需临时缩放,可在
onEnded内将累加值清零即可。
示例
struct MagnificationGestureBootcamp: View {
@State var currentAmount: CGFloat = 0 // 当前增量
// 保留上一次的放大(缩小的)的比例
@State var lastAmount: CGFloat = 0 // 上次遗留
var body: some View {
// Text("Hello, World!")
// .font(.title)
// .padding(40)
// .background(Color.red.cornerRadius(8))
// .scaleEffect(1.0 + currentAmount + lastAmount) // 总比例
// .gesture(
// // 两个手指同时拖拽屏幕,类似放大图片的动作
// MagnificationGesture()
// .onChanged({ value in
// currentAmount = value - 1 // 仅本次增量
// })
// .onEnded({ value in
// lastAmount = lastAmount + currentAmount // 固化结果
// currentAmount = 0 // 复位增量
// })
// )
VStack {
HStack {
Circle()
.frame(width: 32, height: 32)
Text("Swiftful Thinking")
Spacer()
Image(systemName: "ellipsis")
}
.padding(.horizontal)
Rectangle()
.frame(height: 300)
.scaleEffect(1 + currentAmount)
.gesture(
MagnificationGesture()
.onChanged({ value in
currentAmount = value - 1
})
.onEnded({ value in
withAnimation(.spring) {
currentAmount = 0
}
})
)
HStack {
Image(systemName: "heart.fill")
Image(systemName: "text.bubble.fill")
Spacer()
}
.padding(.horizontal)
.font(.headline)
Text("This is the caption for my photo!")
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal)
}
}
}
注意事项
- 缩放中心为视图几何中心;如需指定锚点,请使用
.scaleEffect(_, anchor:)。 - 同时存在
DragGesture或RotationGesture时,可用.simultaneousGesture或GestureMask组合。 - 数值增量为相对 1.0 的偏移,记得计算总比例时加 1。