Skip to content

Instantly share code, notes, and snippets.

@ohayon
Last active April 5, 2023 16:24
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ohayon/83305d9c48e4fc3e7c3851ba10ddc4c9 to your computer and use it in GitHub Desktop.
Save ohayon/83305d9c48e4fc3e7c3851ba10ddc4c9 to your computer and use it in GitHub Desktop.
Example of making a reusable `draggable()` modifier for SwiftUI Views
struct DraggablePita: View {
var body: some View {
Image(uiImage: UIImage(named: "pita.png")!)
.draggable() // Add the new, custom modifier to make this draggable
}
}
// Handle dragging
struct DraggableView: ViewModifier {
@State var offset = CGPoint(x: 0, y: 0)
func body(content: Content) -> some View {
content
.gesture(DragGesture(minimumDistance: 0)
.onChanged { value in
self.offset.x += value.location.x - value.startLocation.x
self.offset.y += value.location.y - value.startLocation.y
})
.offset(x: offset.x, y: offset.y)
}
}
// Wrap `draggable()` in a View extension to have a clean call site
extension View {
func draggable() -> some View {
return modifier(DraggableView())
}
}
@lockieluke
Copy link

it freezes my app lol

@ohayon
Copy link
Author

ohayon commented Mar 27, 2023

hey @lockieluke ! this code is almost 4 years old, i'm not surprised it doesnt work anymore 😄

@lockieluke
Copy link

lockieluke commented Apr 5, 2023

import Foundation
import SwiftUI
import Throttler

struct DraggableView: ViewModifier {
    
    @State private var offset = CGPoint(x: 0, y: 0)
    @Binding private var allowDragging: Bool
    
    private let onDrag: ((_ offset: CGPoint) -> Void)?
    
    init(onDrag: ((_ offset: CGPoint) -> Void)? = nil, allowDragging: Binding<Bool> = .constant(true)) {
        self.onDrag = onDrag
        self._allowDragging = allowDragging
    }
    
    func body(content: Content) -> some View {
        if allowDragging {
            content.gesture(DragGesture(coordinateSpace: .global)
                .onChanged { value in
                    self.offset.x = value.location.x - value.startLocation.x
                    self.offset.y = value.location.y - value.startLocation.y
                    
                    self.onDrag?(self.offset)
                }
                .onEnded { value in
                    withAnimation(.interactiveSpring()) {
                        self.offset = .zero
                    }
                }
            )
            .offset(x: offset.x, y: offset.y)
        } else {
            content
        }
    }
    
}

Fixed it but you'll have to use Throttler

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment