Created
February 5, 2019 18:56
-
-
Save raxityo/b50141880f543dcf41c44b08611e841c to your computer and use it in GitHub Desktop.
Sample ViewController to simulate simple Drag and Drop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class DragAndDropViewController: UIViewController, UIGestureRecognizerDelegate { | |
private var sourceView: UIView! | |
private var dropArea: UIView! | |
private var objectSize = CGSize(width: 100, height: 100) | |
private var originalPosition = CGPoint.zero | |
override func loadView() { | |
self.view = UIView() | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
setupView() | |
} | |
private func setupView() { | |
// Initialize | |
sourceView = UIView(frame: CGRect(origin: .zero, size: objectSize)) | |
sourceView.backgroundColor = .red | |
dropArea = UIView(frame: CGRect(origin: CGPoint(x: 250, y: 500), size: objectSize)) | |
dropArea.backgroundColor = .blue | |
// Add Gesture | |
sourceView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(didLongPressSource))) | |
// setup root | |
view.addSubview(dropArea) | |
view.addSubview(sourceView) | |
} | |
var touchOffset = CGPoint.zero | |
@objc private func didLongPressSource(gesture: UIGestureRecognizer) { | |
switch(gesture.state) { | |
case .began: | |
touchOffset = gesture.location(in: sourceView) | |
case .changed: | |
// 1. get moved position | |
let location = gesture.location(in: view) - touchOffset | |
// 2. Move there | |
sourceView.frame.origin = location | |
case .ended: | |
// 1. get current position | |
let location = gesture.location(in: view) - touchOffset | |
// 2. check if we're closer to start or the end | |
let distanceFromOrigin = location.distance(from: originalPosition) | |
let distanceFromDropZone = location.distance(from: dropArea.frame.origin) | |
let targetPosition = distanceFromOrigin > distanceFromDropZone ? dropArea.frame.origin : originalPosition | |
// 3. move to the closest point | |
UIView.animate(withDuration: 0.3) { | |
self.sourceView.frame.origin = targetPosition | |
} | |
default: | |
break | |
} | |
} | |
} | |
extension CGPoint { | |
func distance(from anotherPoint: CGPoint) -> CGFloat { | |
let dx = abs(x - anotherPoint.x) | |
let dy = abs(y - anotherPoint.y) | |
return sqrt(dx*dx + dy*dy) | |
} | |
static func +(_ one: CGPoint,_ other: CGPoint) -> CGPoint { | |
return CGPoint(x: one.x + other.x, y: one.y + other.y) | |
} | |
static func -(_ one: CGPoint,_ other: CGPoint) -> CGPoint { | |
return CGPoint(x: one.x - other.x, y: one.y - other.y) | |
} | |
} | |
// To use this VC in a playground: | |
import PlaygroundSupport | |
PlaygroundPage.current.liveView = DragAndDropViewController() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment