You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中MagnificationGesture手势状态在手势间重置问题求助

解决SwiftUI MagnificationGesture重置缩放状态的问题

你的代码存在两个核心问题导致缩放状态无法保留:

  1. scale是普通变量,没有用@State修饰,无法在视图生命周期中保留状态,也不能触发视图更新。
  2. MagnificationGesture的value是相对于当前手势起始点的缩放倍数(每次新手势启动时都会从1开始计算),直接将value赋值给scale会覆盖之前的缩放结果。

以下是修复后的代码:

import SwiftUI

struct ContentView2: View {
    // 使用@State修饰,让scale成为可观察的状态变量,保留视图状态
    @State private var scale: CGFloat = 1
    // 记录手势开始前的缩放基准值
    @State private var lastScale: CGFloat = 1
    
    var magnificationGesture: some Gesture {
        MagnificationGesture()
            // 手势开始时,保存当前的缩放值作为基准
            .onBegin { _ in
                lastScale = scale
            }
            // 手势过程中,用基准值乘以手势的相对缩放倍数,得到总缩放比例
            .onChanged { value in
                scale = lastScale * value
            }
    }
    
    var body: some View {
        VStack {
            Text(String(format: "%.2f", scale))
            Spacer()
            Rectangle()
                .fill(Color.red)
                .scaleEffect(scale)
                .gesture(magnificationGesture)
            Spacer()
        }
    }
}

struct ContentView2_Previews: PreviewProvider {
    static var previews: some View {
        ContentView2()
    }
}

关键修改说明:

  • @State修饰符:将scale和lastScale标记为状态变量,SwiftUI会自动跟踪它们的变化,更新视图并保留状态。
  • onBegin回调:每次手势启动时,把当前的scale值存入lastScale,作为本次手势的缩放基准。
  • onChanged计算逻辑:用基准值lastScale乘以手势返回的相对缩放倍数value,这样就能基于上一次的缩放结果继续调整,不会重置为初始值1。

内容的提问来源于stack exchange,提问作者charelf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:05:34