diff --git a/Package.swift b/Package.swift index 26e09a3..53f49b3 100644 --- a/Package.swift +++ b/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "DragAndDrop", - platforms: [.iOS(.v14)], + platforms: [.iOS(.v15)], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. .library( diff --git a/Sources/DragAndDrop/DragView.swift b/Sources/DragAndDrop/DragView.swift index 779a20d..5386454 100644 --- a/Sources/DragAndDrop/DragView.swift +++ b/Sources/DragAndDrop/DragView.swift @@ -7,9 +7,15 @@ import SwiftUI +public struct DragInfo { + public let didDrop: Bool + public let isDragging: Bool + public let isColliding: Bool +} + /// A draging view that needs to be inside a `InteractiveDragDropContainer` to work properly. public struct DragView : View { - + @EnvironmentObject private var manager: DragDropManager @State private var dragOffset: CGSize = CGSize.zero @@ -21,12 +27,6 @@ public struct DragView : View { private var dragginStoppedAction: ((_ isSuccessfullDrop: Bool) -> Void)? private let elementID: UUID - public struct DragInfo { - public let didDrop: Bool - public let isDragging: Bool - public let isColliding: Bool - } - /// Initialize this view with its unique ID and custom view. /// /// - Parameters: @@ -45,12 +45,14 @@ public struct DragView : View { else{ content(DragInfo(didDrop: isDroped, isDragging: isDragging, isColliding: manager.isColliding(dragID: elementID))) .offset(dragOffset) - .overlay(GeometryReader(content: { geometry in - Color.clear - .onAppear { - self.manager.addFor(drag: elementID, frame: geometry.frame(in: .dragAndDrop)) - } - })) + .background { + GeometryReader { geometry in + Color.clear + .onAppear { + self.manager.addFor(drag: elementID, frame: geometry.frame(in: .dragAndDrop)) + } + } + } .gesture( DragGesture() .onChanged { value in @@ -58,31 +60,13 @@ public struct DragView : View { dragOffset = value.translation } } - .simultaneously(with: DragGesture(coordinateSpace: .dragAndDrop) - .onChanged { value in - manager.report(drag: elementID, offset: value.translation) - - if !isDragging { - isDragging = true - } - } - .onEnded { value in - if manager.canDrop(id: elementID, offset: value.translation) { - manager.dropDragView(of: elementID, at: value.translation) - isDroped = true - dragginStoppedAction?(true) - } else { - withAnimation(.spring()) { - dragOffset = CGSize.zero - } - dragginStoppedAction?(false) - } - isDragging = false - } - ) + .simultaneously(with: + DragGesture(coordinateSpace: .dragAndDrop) + .onChanged(onDragChanged(_:)) + .onEnded(onDragEnded(_:)) + ) ) .zIndex(isDragging ? 1 : 0) - .animation(.spring(), value: isDragging) } } @@ -96,4 +80,26 @@ public struct DragView : View { new.dragginStoppedAction = action return new } + + private func onDragChanged(_ value: DragGesture.Value) { + manager.report(drag: elementID, offset: value.translation) + + if !isDragging { + isDragging = true + } + } + + private func onDragEnded(_ value: DragGesture.Value) { + if manager.canDrop(id: elementID, offset: value.translation) { + manager.dropDragView(of: elementID, at: value.translation) + isDroped = true + dragginStoppedAction?(true) + } else { + withAnimation(.spring()) { + dragOffset = CGSize.zero + } + dragginStoppedAction?(false) + } + isDragging = false + } } diff --git a/Sources/DragAndDrop/DropView.swift b/Sources/DragAndDrop/DropView.swift index 152a94a..ba004df 100644 --- a/Sources/DragAndDrop/DropView.swift +++ b/Sources/DragAndDrop/DropView.swift @@ -7,6 +7,11 @@ import SwiftUI +public struct DropInfo { + public let didDrop: Bool + public let isColliding: Bool +} + /// A drop view that needs to be inside a `InteractiveDragDropContainer` to work properly. public struct DropView: View { @@ -19,11 +24,6 @@ public struct DropView: View { private let content: (_ dragInfo: DropInfo) -> Content private var receivedAction: ((_ receivingViewID: UUID) -> Void)? - public struct DropInfo { - public let didDrop: Bool - public let isColliding: Bool - } - /// Initializer for the drop view that uses the id of the receiving drag view. /// /// - Parameters: @@ -41,16 +41,18 @@ public struct DropView: View { public var body: some View { content(DropInfo(didDrop: isDropped, isColliding: manager.isColliding(dropId: elementID))) - .overlay(GeometryReader(content: { geometry in - Color.clear - .onAppear { - self.manager.addFor( - drop: elementID, - frame: geometry.frame(in: .dragAndDrop), - canRecieveAnyDragView: canRecieveAnyDragView - ) - } - })) + .background { + GeometryReader { geometry in + Color.clear + .onAppear { + self.manager.addFor( + drop: elementID, + frame: geometry.frame(in: .dragAndDrop), + canRecieveAnyDragView: canRecieveAnyDragView + ) + } + } + } .onChange(of: manager.droppedViewID) { newValue in if newValue == elementID { isDropped = true diff --git a/Tests/DragAndDropTests/DragAndDropTests.swift b/Tests/DragAndDropTests/DragAndDropTests.swift index 2465b78..e4fe04b 100644 --- a/Tests/DragAndDropTests/DragAndDropTests.swift +++ b/Tests/DragAndDropTests/DragAndDropTests.swift @@ -6,6 +6,6 @@ final class DragAndDropTests: XCTestCase { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct // results. - XCTAssertEqual(DragAndDrop().text, "Hello, World!") + //XCTAssertEqual(DragAndDrop().text, "Hello, World!") } }