Drag-and-drop is an intuitive gesture and can improve the UX of an app.
Chess | Emoji Art | Card Game | To Do List |
---|---|---|---|
Documentation | Documentation | Documentation | Documentation |
This library supports drag-and-drop in SwiftUI code. This is a replacement for the native onDrag
/ onDrop
and their limitations.
This library is a good fit if your use case falls into one or more of the following:
The following steps will get your project compiling with a basic implementation of the library.
DropReceiver
and conform the struct to it:protocol DropReceiver {
var dropArea: CGRect? { get set }
}
For example:
struct MyDropReceiver: DropReceiver {
var dropArea: CGRect? = nil
}
DropReceivableObservableObject
& Add a variable in the ViewModel referencing the DropReceiver
struct.protocol DropReceivableObservableObject: ObservableObject {
associatedtype DropReceivable: DropReceiver
func setDropArea(_ dropArea: CGRect, on dropReceiver: DropReceivable)
}
For example:
class DragAndDropViewModel: DropReceivableObservableObject {
typealias DropReceivable = MyDropReceiver
var dropReceiver = MyDropReceiver()
func setDropArea(_ dropArea: CGRect, on dropReceiver: DropReceivable) {
dropReceiver.updateDropArea(with: dropArea)
}
}
.dropArea(for:model:)
to an element in your View which represents the DropReceiver
struct. The for:
should be an element of the type of the DropReceiver
struct and the model:
should be a reference to the DropReceivableObservableObject
ViewModel.For example:
struct MyDragAndDropView: View {
@State var model = DragAndDropViewModel()
var body: some View {
VStack {
Rectangle()
.dropReceiver(for: model.dropReceiver, model: model)
}
}
}
.dragable()
to any other element in the View. The code can now run and the View is draggable. It will show a blue shadow while dragging.For example:
var body: some View {
VStack {
Rectangle()
.frame(width: 150, height: 150)
.dropReceiver(for: model.dropReceiver, model: model)
Spacer()
Circle()
.frame(width: 50, height: 50)
.dragable()
}
.padding()
}
.dragable(onDragged:onDropped:)
, respectively. func onDragged(position: CGPoint) -> DragState {
if model.dropReceiver.getDropArea()!.contains(position) {
return .accepted
} else {
return .rejected
}
}
func onDropped(position: CGPoint) -> Bool {
model.dropReceiver.getDropArea()!.contains(position)
}
This code will allow a user to drag the object marked dragable
and the shadow will now be green if the drop receiver is below the drag gesture or red if it is not.
These examples are intended to showcase various implementations of drag-and-drop and are not intended to be full apps. Since drag-and-drop is a means of signaling user intent, these examples show various ways to capture that intent.
Emoji Art.
View the code. | Read the Documentation.
This example shows a single drop receiver (the canvas) and multiple drag-and-drop objects (the emoji on the palette & the emoji on the canvas).
To Do App.
View the code. | Read the Documentation.
A todo list where each list object can be dragged on top of a "Complete" box or a "Trash" box. The "Add New" button is draggable on top of the list to add a new object.
Chess Board.
View the code. | Read the Documentation.
This example shows how to implement drag-and-drop chess pieces on the chess board. The only movement rules are basic directional rules. The movement rules do not enforce check, checkmate, turn order, or board-wrapping (that is, a bishop on a3 can move to h3 as described here).
Card Game.
View the code. | Read the Documentation.
In this game, players can play a card in one of three playable areas: here, there, or yonder. Each card can be played in 1 or more of these areas.
Working with Non-Rectangular Drop Areas.
This tutorial covers working with non-rectangular drop areas on a map or in a non-rectangular grid.
link |
Stars: 26 |
Last commit: 1 year ago |
This release fixes a bug where onRotate would not update dropReceivers' dropAreas on iPad and on iPhones running iOS 16 or higher.
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics