SheetImagePicker/SheetImagePicker/SheetContainerViewControlle...

90 lines
3.0 KiB
Swift

//
// SheetContainerViewController.swift
// SheetImagePicker
//
// Created by Shadowfacts on 9/23/19.
// Copyright © 2019 Shadowfacts. All rights reserved.
//
import UIKit
public class SheetContainerViewController: UIViewController {
let content: UIViewController
public var detents: [Detent] = [.bottom, .middle, .top] {
didSet {
}
}
var topConstraint: NSLayoutConstraint!
lazy var initialConstant: CGFloat = view.bounds.height / 2
public init(content: UIViewController) {
self.content = content
super.init(nibName: nil, bundle: nil)
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func viewDidLoad() {
super.viewDidLoad()
addChild(content)
content.didMove(toParent: self)
view.addSubview(content.view)
topConstraint = content.view.topAnchor.constraint(equalTo: view.topAnchor, constant: initialConstant)
NSLayoutConstraint.activate([
content.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
content.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
topConstraint,
content.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureRecognized(_:)))
content.view.addGestureRecognizer(panGesture)
}
@objc func panGestureRecognized(_ recognizer: UIPanGestureRecognizer) {
switch recognizer.state {
case .began:
initialConstant = topConstraint.constant
case .changed:
let translation = recognizer.translation(in: content.view)
var realOffset = initialConstant + translation.y
if realOffset < view.safeAreaInsets.top {
print(realOffset)
realOffset = view.safeAreaInsets.top - realOffset / pow(CGFloat(M_E), realOffset / view.safeAreaInsets.top)
}
topConstraint.constant = realOffset
case .ended:
if let offset = nearestDetentOffset(offset: topConstraint.constant) {
let distance = abs(topConstraint.constant - offset)
self.topConstraint.constant = offset
let velocity = recognizer.velocity(in: view)
let springVelocity = velocity.y / distance
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: springVelocity, animations: {
self.view.layoutIfNeeded()
})
}
default:
return
}
}
func nearestDetentOffset(offset: CGFloat) -> CGFloat? {
return detents.map { $0.offset(in: view) }.min { (a, b) -> Bool in
return abs(offset - a) < abs(offset - b)
}
}
}