Skip to content

Instantly share code, notes, and snippets.

@macbellingrath
Last active April 2, 2017 13:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save macbellingrath/08a54ffc08f39c650181688a625d4d7f to your computer and use it in GitHub Desktop.
Save macbellingrath/08a54ffc08f39c650181688a625d4d7f to your computer and use it in GitHub Desktop.
import UIKit
import PlaygroundSupport
class FirstTable: UITableViewController, UIViewControllerTransitioningDelegate {
lazy var animator = TransitionAnimator()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "reuseID")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseID", for: indexPath)
cell.textLabel?.text = "Press Me"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let second = SecondTable(style: UITableViewStyle.grouped)
second.transitioningDelegate = self
present(second, animated: true, completion: nil)
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animator.isPresenting = true
return animator
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
animator.isPresenting = false
return animator
}
}
class TransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
let duration: Double = 1
var isPresenting = true
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
if isPresenting {
animatePresentation(using: transitionContext)
} else {
animateDismissal(using: transitionContext)
}
}
func animatePresentation(using transitionContext: UIViewControllerContextTransitioning){
guard let toVC = transitionContext.viewController(forKey: .to) as? UITableViewController else {
return
}
let yTransform: CGFloat = 10
for cell in toVC.tableView.visibleCells{
cell.alpha = 0
cell.transform = cell.transform.translatedBy(x: 0, y: yTransform)
}
toVC.view.alpha = 0.8
let containerView = transitionContext.containerView
containerView.addSubview(toVC.view)
let duration = transitionDuration(using: transitionContext)
let count = Double(toVC.tableView.indexPathsForVisibleRows?.count ?? 1)
let totalDelay = 0.01 * count
let individualDelay = totalDelay / count
let leftOverTime = duration - totalDelay
let individualDuration = leftOverTime / count
for (offset, cell) in toVC.tableView.visibleCells
.reversed()
.enumerated() {
UIView.animate(withDuration: individualDuration, delay: individualDelay * Double(offset), usingSpringWithDamping: 0.2, initialSpringVelocity: 10, options: [], animations: {
cell.alpha = 1
cell.transform = .identity
}, completion: nil)
}
UIView.animate(withDuration: duration, animations: {
toVC.view.alpha = 1
}, completion: { finished in
let cancelled = transitionContext.transitionWasCancelled
transitionContext.completeTransition(!cancelled)
})
}
func animateDismissal(using transitionContext: UIViewControllerContextTransitioning){
guard let fromVC = transitionContext.viewController(forKey: .from) as? UITableViewController else {
return
}
let containerView = transitionContext.containerView
containerView.addSubview(fromVC.view)
let duration = transitionDuration(using: transitionContext)
let count = Double(fromVC.tableView.indexPathsForVisibleRows?.count ?? 1)
let totalDelay = 0.01 * count
let individualDelay = totalDelay / count
let leftOverTime = duration - totalDelay
let individualDuration = leftOverTime / count
for (offset, cell) in fromVC.tableView.visibleCells
.reversed()
.enumerated() {
UIView.animate(withDuration: individualDuration, delay: individualDelay * Double(offset), usingSpringWithDamping: 0.2, initialSpringVelocity: 10, options: [], animations: {
cell.alpha = 1
cell.transform = cell.transform.translatedBy(x: 0, y: 100)
}, completion: nil)
}
UIView.animate(withDuration: duration, animations: {
fromVC.view.alpha = 0
}, completion: { finished in
let cancelled = transitionContext.transitionWasCancelled
transitionContext.completeTransition(!cancelled)
})
}
}
class SecondTable: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "reuseID")
automaticallyAdjustsScrollViewInsets = false
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseID", for: indexPath)
cell.textLabel?.text = "WWDC"
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
dismiss(animated: true, completion: nil)
}
}
PlaygroundPage.current.liveView = FirstTable(style: .plain)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment