Skip to content

Instantly share code, notes, and snippets.

@RamonGilabert
Last active June 30, 2016 21:50
Show Gist options
  • Save RamonGilabert/d6d7fa825e549172641b7595044cabb0 to your computer and use it in GitHub Desktop.
Save RamonGilabert/d6d7fa825e549172641b7595044cabb0 to your computer and use it in GitHub Desktop.
import UIKit
class ViewController: UIViewController {
struct Constants {
static let offset: CGFloat = 5
static let height: CGFloat = 300
static let maximum: CGFloat = Constants.height + Constants.offset
static let maximumY = UIScreen.mainScreen().bounds.height - Constants.maximum
static let velocity: CGFloat = 250
static let arrel: CGFloat = 0.6
static let sticky: CGFloat = 60
}
lazy var bottomView: BottomView = { [unowned self] in
let view = BottomView()
view.backgroundColor = UIColor(red:0.98, green:0.98, blue:0.97, alpha:1.00)
view.layer.cornerRadius = 10
view.translatesAutoresizingMaskIntoConstraints = false
view.addGestureRecognizer(self.panGesture)
return view
}()
lazy var panGesture: UIPanGestureRecognizer = { [unowned self] in
let gesture = UIPanGestureRecognizer()
gesture.addTarget(self, action: #selector(handlePanGesture(_:)))
return gesture
}()
var animator: UIDynamicAnimator?
var snapBehavior: UISnapBehavior?
var itemBehavior: UIDynamicItemBehavior?
var attachmentBehavior: UIAttachmentBehavior?
var origin: CGPoint = CGPoint.zero
var bottomDown: Bool = true
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(bottomView)
view.backgroundColor = UIColor(red: 0.08, green: 0.09, blue: 0.09, alpha: 1.00)
animator = UIDynamicAnimator(referenceView: view)
setupConstraints()
}
// MARK: - Gesture
func handlePanGesture(gesture: UIPanGestureRecognizer) {
let velocity = gesture.velocityInView(view)
var translation = gesture.translationInView(view)
translation.x = CGRectGetMidX(bottomView.bounds)
if gesture.state == .Began {
if let behavior = snapBehavior, itemBehavior = itemBehavior {
animator?.removeBehavior(behavior)
animator?.removeBehavior(itemBehavior)
}
origin = bottomView.frame.origin
attachmentBehavior = UIAttachmentBehavior(
item: bottomView, attachedToAnchor:
CGPoint(x: origin.x + translation.x, y: origin.y + translation.y))
bottomDown = origin.y > Constants.maximumY
if let behavior = attachmentBehavior {
animator?.addBehavior(behavior)
}
} else if gesture.state == .Changed {
if bottomView.frame.origin.y < Constants.maximumY {
let number = (origin.y + translation.y) / Constants.maximumY
attachmentBehavior?.anchorPoint.y = Constants.maximumY * smaller(sqrt(number), Constants.arrel)
} else {
attachmentBehavior?.anchorPoint.y = origin.y + translation.y
}
} else {
if let behavior = attachmentBehavior {
animator?.removeBehavior(behavior)
}
let condition = abs(translation.y) > Constants.sticky
|| abs(velocity.y) > Constants.velocity ? velocity.y < 0 : !bottomDown
condition ? snapView(Constants.maximum) : snapView(Constants.sticky)
}
}
// MARK: - Dynamic methods
func snapView(value: CGFloat) {
let size = UIScreen.mainScreen().bounds.size
snapBehavior = UISnapBehavior(item: bottomView, snapToPoint: CGPoint(
x: size.width / 2,
y: size.height + Constants.height / 2 - value))
snapBehavior?.damping = 0.15
itemBehavior = UIDynamicItemBehavior(items: [bottomView])
itemBehavior?.allowsRotation = false
if let behavior = snapBehavior, itemBehavior = itemBehavior {
animator?.addBehavior(behavior)
animator?.addBehavior(itemBehavior)
}
}
// MARK: - Helper methods
func smaller(ln: CGFloat, _ rn: CGFloat) -> CGFloat {
return ln < rn ? rn : ln
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
// MARK: - Constraints
func setupConstraints() {
NSLayoutConstraint.activateConstraints([
bottomView.widthAnchor.constraintEqualToAnchor(view.widthAnchor, constant: -Constants.offset * 2),
bottomView.heightAnchor.constraintEqualToConstant(Constants.height),
bottomView.rightAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -Constants.offset),
bottomView.topAnchor.constraintEqualToAnchor(view.bottomAnchor, constant: -Constants.sticky)
])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment