๐Ÿ‘”.draggable()

SwiftUI โŸฉ Gestures โŸฉ Drag โŸฉ .draggable()

import SwiftUI

// ๐Ÿ‘” Draggable
struct Draggable: ViewModifier {
    
    // ๐Ÿ”ธ ๆญค่ฎŠๆ•ธ็›ฎๅ‰ๆฒ’ไป€้บผ็”จ๏ผŒไฝ†ๅœจๅ…ถไป–็‹€ๆณไธ‹๏ผŒไนŸ่จฑๅฏๆดพไธŠ็”จๅ ดใ€‚
    @State var isDragging = false
    
    // ๐Ÿ”ธ ๆ‹–ๆ›ณๆ™‚๏ผŒoffset ๆœƒ้šจๆ™‚ๆ›ดๆ–ฐ๏ผŒไฝ† dragOffset ไฟๆŒไธ่ฎŠใ€‚
    //    ๆฒ’ๆ‹–ๆ›ณๆ™‚๏ผŒๅ…ฉ่€…ๆ˜ฏไธ€ๆจฃ็š„ใ€‚
    @State private var offset = CGSize.zero        // current offset
    @State private var dragOffset = CGSize.zero    // prev accumulative offset
    
    // โญ๏ธ optional event handlers
    typealias OffsetHandler = (CGSize) -> Void
    var onChanged: OffsetHandler?
    var onEnded  : OffsetHandler?
    
    func body(content: Content) -> some View {
        content
            .offset(offset)        // โญ๏ธ apply offset
            .gesture(
                DragGesture()
                    .onChanged { value in
                        isDragging = true
                        // update offset
                        offset = dragOffset + value.translation
                        // event handler
                        onChanged?(offset)
                    }
                    .onEnded { value in
                        isDragging = false
                        // update offset
                        offset = dragOffset + value.translation
                        // โญ๏ธ save accumulative offset
                        dragOffset = offset
                        // event handler
                        onEnded?(offset)
                    }
            )
    }
}

// ๐ŸŒ€ View+ .draggable()
extension View {
    /// `view.draggable(onChanged:onEnded:)`
    func draggable(
        onChanged: Draggable.OffsetHandler? = nil, 
        onEnded  : Draggable.OffsetHandler? = nil
    ) -> some View {
        modifier(Draggable(onChanged: onChanged, onEnded: onEnded))
    }
}

Last updated