Search code examples
iosswiftswiftuidraggesture

Flashing issue with the view while dragging in SwiftUI


I am planning to implement dragging of the entire view by dragging the Image view, but there is a flickering issue during the process. If I move the gesture code to the ZStack, the flickering disappears, but I need the operation to be limited to the Image only.

import SwiftUI
struct MyGestureView: View {
    var x: CGFloat = 200
    var y: CGFloat = 200
    @GestureState var dragGesture = CGSize.zero
    @State var startPosition = CGSize.zero
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color.red)
                .stroke(Color.white, lineWidth: 0.8)
                .frame(width: 180, height: 50)
                .cornerRadius(10)
                .contentShape(Rectangle())
            Text("hello").frame(width: 180, height: 50)
                .foregroundColor(.white)
            Image(systemName: "gobackward")
                .foregroundColor(.white)
                .background(.gray)
                .clipShape(Circle())
                .offset(x: 90, y: 25)
                .gesture(DragGesture().updating($dragGesture, body: {
                    value, state, _ in
                    state = value.translation
                    print(dragGesture)
                }).onEnded { value in
                    startPosition.width = startPosition.width + value.translation.width
                    startPosition.height = startPosition.height + value.translation.height
                })
        }
        .position(x: x, y: y)
        .offset(x: startPosition.width + dragGesture.width, y: startPosition.height + dragGesture.height)
    }
}

#Preview {
    MyGestureView()
}

If I move the gesture code to the ZStack, the flickering disappears, but I need the operation to be limited to the Image only.


Solution

  • Here's how you can implement dragging of the entire view by dragging the Image without flickering, limiting the operation to the Image only, without moving the gesture code to the ZStack. I hope this solves your query.

    enter image description here

    import SwiftUI
    
    struct MyGestureView: View {
        
        @State private var startPosition: CGSize = .zero
        @State private var currentPosition: CGSize = .zero
        @GestureState private var dragState: CGSize = .zero
        
        var body: some View {
            let dragGesture = DragGesture()
                .onChanged { value in
                    self.currentPosition = CGSize(
                        width: self.startPosition.width + value.translation.width,
                        height: self.startPosition.height + value.translation.height
                    )
                }
                .onEnded { value in
                    self.startPosition = self.currentPosition
                }
            
            ZStack {
                Rectangle()
                    .fill(Color.red)
                    .stroke(Color.white, lineWidth: 0.8)
                    .frame(width: 180, height: 50)
                    .cornerRadius(10)
                    .offset(currentPosition)
                
                Text("hello")
                    .frame(width: 180, height: 50)
                    .foregroundColor(.white)
                    .offset(currentPosition)
                
                Image(systemName: "gobackward")
                    .foregroundColor(.white)
                    .background(Color.gray)
                    .clipShape(Circle())
                    .offset(x: 90, y: 25)
                    .offset(currentPosition)
                    .gesture(dragGesture)
            }
            .position(x: 200, y: 200)
        }
    }
    
    
    #Preview {
        MyGestureView()
    }