Search code examples
swiftuigesture

SwiftUI gesture state is reset between gestures


I have the following code for a simple square to which I attach a MagnificationGesture to update its state with a pinch to zoom gesture.

import SwiftUI

struct ContentView2: View {
    
    var scale: CGFloat = 1
    
    var magnificationGesture: some Gesture {
        MagnificationGesture()
            .onChanged { value in
                scale = value
            }
    }
    
    var body: some View {
        VStack {
            Text("\(scale)")
            Spacer()
            Rectangle()
                .fill(Color.red)
                .scaleEffect(self.scale)
                .gesture(
                    magnificationGesture
                )
            Spacer()
        }
    }
}

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

However this simple view behaves weird. When I perform the gesture, the scale @State property is succesfully modified. However when I then do another gesture with my hands, the scale property is reset to its initial state, instead of starting from its current value.

Here is a video of what happens. For example, when the red view is very small, performing the gesture, I would expect that it stays small, instead of completely resetting.

How can I get the desired behaviour - that is - the scale property is not reset

enter image description here


Solution

  • I was able to get it working by adding a bit to the code. Check it out and let me know if this works for your use case:

      import SwiftUI
    
    struct ContentView2: View {
        var magGesture = MagnificationGesture()
        @State var magScale: CGFloat = 1
        @State var progressingScale: CGFloat = 1
        
        var magnificationGesture: some Gesture {
            magGesture
                .onChanged { progressingScale = $0 }
                .onEnded {
                    magScale *= $0
                    progressingScale = 1
                }
        }
        
        var body: some View {
            VStack {
                Text("\(magScale)")
                Spacer()
                Rectangle()
                    .fill(Color.red)
                    .scaleEffect(self.magScale * progressingScale)
                
                    .gesture(
                        magnificationGesture
                    )
                Spacer()
            }
        }
    }
    
    struct ContentView2_Previews: PreviewProvider {
        static var previews: some View {
            ContentView2()
        }
    }