Created
September 5, 2016 16:02
-
-
Save Darmaal/d374a3a685ee9a733b0f6670da905c45 to your computer and use it in GitHub Desktop.
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 ViewController: UIViewController, UICollisionBehaviorDelegate { | |
let data = ["Getting sstartw with Swift","SiriKit Basic","SprieKit for Apple Watch"] | |
var views = [UIView]() | |
var animator:UIDynamicAnimator! | |
var gravity:UIGravityBehavior! | |
var snap:UISnapBehavior! | |
var previousTouchPoint:CGPoint! | |
var viewDragging = false | |
var viewPinned = false | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
animator = UIDynamicAnimator(referenceView: self.view) | |
gravity = UIGravityBehavior() | |
animator.addBehavior(gravity) | |
gravity.magnitude = 4 | |
var offset:CGFloat = 250 | |
for i in 0 ... data.count - 1 { | |
if let view = addViewController(atOffset: offset, dataForVC: data[i]){ | |
views.append(view) | |
offset -= 50 | |
} | |
} | |
} | |
//optional return | |
func addViewController (atOffset offset:CGFloat, dataForVC data:AnyObject?) -> UIView? { | |
let frameForView = self.view.bounds.offsetBy(dx: 0, dy: self.view.bounds.size.height - offset) | |
let sb = UIStoryboard(name: "Main", bundle: nil) | |
let stackElementVC = sb.instantiateViewControllerWithIdentifier("StackElement") as! SEVC | |
if let view = stackElementVC.view { | |
view.frame = frameForView | |
view.layer.cornerRadius = 5 | |
view.layer.shadowOffset = CGSizeMake(2, 2) | |
view.layer.shadowColor = UIColor.blackColor().CGColor | |
view.layer.shadowRadius = 3 | |
view.layer.shadowOpacity = 0.5 | |
//adding some data to our controller | |
if let headerStr = data as? String { | |
stackElementVC.headerString = headerStr | |
} | |
self.addChildViewController(stackElementVC) | |
self.view.addSubview(view) | |
stackElementVC.didMoveToParentViewController(self) | |
//pan gesture recognizer | |
//let pGr = UIPanGestureRecognizer(target: self, action: #selector(ViewController.handle) | |
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(ViewController.handlePan(_:))) | |
view.addGestureRecognizer(panGestureRecognizer) | |
let collision = UICollisionBehavior(items: [view]) | |
//the following line is used to create the snappy smooth animation effect | |
collision.collisionDelegate = self | |
animator.addBehavior(collision) | |
//defining a boundary | |
let boundary = view.frame.origin.y + view.frame.size.height | |
// lower boundary | |
var boundaryStart = CGPoint(x: 0, y: boundary) | |
var boundaryEnd = CGPoint(x: self.view.bounds.size.width, y: boundary) | |
collision.addBoundaryWithIdentifier(1, fromPoint: boundaryStart, toPoint: boundaryEnd) | |
// upper boundary | |
boundaryStart = CGPoint(x: 0, y: 0) | |
boundaryEnd = CGPoint(x: self.view.bounds.size.width, y: 0) | |
collision.addBoundaryWithIdentifier(2, fromPoint: boundaryStart, toPoint: boundaryEnd) | |
gravity.addItem(view) | |
let itemBehavior = UIDynamicItemBehavior(items: [view]) | |
animator.addBehavior(itemBehavior) | |
return view | |
} | |
return nil | |
} | |
func handlePan (gestureRecognizer:UIPanGestureRecognizer){ | |
//getting the toucpoint -> where did our user click in hte screen | |
// let touchPoint = gestureRecognizer.locationOfTouch(in:, inView: self.view) | |
//let draggedView = gestureRecognizer.view! | |
let touchPoint = gestureRecognizer.locationInView(self.view) | |
let draggedView = gestureRecognizer.view! | |
if gestureRecognizer.state == .Began { | |
let dragStartPoint = gestureRecognizer.locationInView(draggedView) | |
// the y value here is fully depended on your scaling, meaning you can readjust this to your desire | |
if dragStartPoint.y < 200 { | |
viewDragging = true | |
previousTouchPoint = touchPoint | |
} | |
} else if gestureRecognizer.state == .Changed && viewDragging { | |
let yOffset = previousTouchPoint.y - touchPoint.y | |
draggedView.center = CGPoint(x: draggedView.center.x, y:draggedView.center.y - yOffset) | |
previousTouchPoint = touchPoint | |
} else if gestureRecognizer.state == .Ended && viewDragging { | |
pin(draggedView) | |
addVelocity(toView: draggedView, fromGestureRecgonizer: gestureRecognizer) | |
animator.updateItemUsingCurrentState(draggedView) | |
viewDragging = false | |
} | |
} | |
//determinor | |
func pin (view:UIView){ | |
let viewHasReachedPinLocation = view.frame.origin.y < 100 | |
if viewHasReachedPinLocation { | |
if !viewPinned { | |
//creating the snappy behavior | |
var snapPosition = self.view.center | |
snapPosition.y += 30 | |
snap = UISnapBehavior(item: view, snapToPoint: snapPosition) | |
animator.addBehavior(snap) | |
setVisibility(view, alpha: 0) | |
viewPinned = true | |
} | |
} else { | |
if viewPinned { | |
animator.removeBehavior(snap) | |
setVisibility(view, alpha: 1) | |
viewPinned = false | |
} | |
} | |
} | |
func setVisibility(view:UIView, alpha:CGFloat){ | |
for aView in views { | |
if aView != view { | |
aView.alpha = alpha | |
} | |
} | |
} | |
//detects if one of the items is thrown, and attempt to apply semi-realistic physics to it | |
func addVelocity(toView view:UIView, fromGestureRecgonizer panGesture:UIPanGestureRecognizer){ | |
var velocity = panGesture.velocityInView(self.view) | |
velocity.x = 0 | |
if let behavior = itemBehavior(forview: view){ | |
behavior.addLinearVelocity(velocity, forItem: view) | |
} | |
} | |
// this function will iterate until it finds the perfect UIDYNBHV, then apply the linaer velocity | |
func itemBehavior (forview view:UIView) ->UIDynamicItemBehavior? { | |
for behavoir in animator.behaviors { | |
if let itemBehavior = behavoir as? UIDynamicItemBehavior { | |
if let possibleView = itemBehavior.items.first as? UIView where possibleView == view { | |
return itemBehavior | |
} | |
} | |
} | |
return nil | |
} | |
// | |
// func collisionBehavior(UICollisionBehavior, beganContactForItem: UIDynamicItem, withBoundaryIdentifier: NSCopying?, atPoint: CGPoint){ | |
// | |
// if NSNumber(IntegerLiteralType: 2).isEqual(identifer){ | |
// | |
// } | |
// | |
// } | |
func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, atPoint p: CGPoint) { | |
if NSNumber(integerLiteral: 2).isEqual(identifier){ | |
let view = item as! UIView | |
pin(view) | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment