Skip to content

Commit

Permalink
try transition animation
Browse files Browse the repository at this point in the history
  • Loading branch information
skyfoxs committed Dec 22, 2019
1 parent 9cfe735 commit 48c9ed8
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Starbucks.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
6B1487F923AB97AF0015D2A1 /* CardTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B1487F823AB97AF0015D2A1 /* CardTableViewCell.swift */; };
D8652DE323ABBB1D00BD2B6F /* CardDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8652DE223ABBB1D00BD2B6F /* CardDetailViewController.swift */; };
D8652DE523ABBE5A00BD2B6F /* String+pdf417Barcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8652DE423ABBE5A00BD2B6F /* String+pdf417Barcode.swift */; };
D8D6F44323AF6A4C00E0CBE0 /* CardAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D6F44223AF6A4C00E0CBE0 /* CardAnimator.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -32,6 +33,7 @@
6B1487F823AB97AF0015D2A1 /* CardTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardTableViewCell.swift; sourceTree = "<group>"; };
D8652DE223ABBB1D00BD2B6F /* CardDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardDetailViewController.swift; sourceTree = "<group>"; };
D8652DE423ABBE5A00BD2B6F /* String+pdf417Barcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+pdf417Barcode.swift"; sourceTree = "<group>"; };
D8D6F44223AF6A4C00E0CBE0 /* CardAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardAnimator.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -71,6 +73,7 @@
D8652DE223ABBB1D00BD2B6F /* CardDetailViewController.swift */,
6B1487F823AB97AF0015D2A1 /* CardTableViewCell.swift */,
6B0F0B8A23AC7BC0000C5AD3 /* GiftView.swift */,
D8D6F44223AF6A4C00E0CBE0 /* CardAnimator.swift */,
D8652DE723AF683B00BD2B6F /* Storyboard */,
D8652DE623AF680D00BD2B6F /* Extension */,
6B1487ED23AB976B0015D2A1 /* Assets.xcassets */,
Expand Down Expand Up @@ -168,6 +171,7 @@
files = (
D8652DE323ABBB1D00BD2B6F /* CardDetailViewController.swift in Sources */,
D8652DE523ABBE5A00BD2B6F /* String+pdf417Barcode.swift in Sources */,
D8D6F44323AF6A4C00E0CBE0 /* CardAnimator.swift in Sources */,
6B1487E923AB976B0015D2A1 /* CardController.swift in Sources */,
6B1487E523AB976B0015D2A1 /* AppDelegate.swift in Sources */,
6B1487E723AB976B0015D2A1 /* SceneDelegate.swift in Sources */,
Expand Down
110 changes: 110 additions & 0 deletions Starbucks/CardAnimator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//
// CardAnimator.swift
// Starbucks
//
// Created by Supakit Thanadittagorn on 22/12/19.
// Copyright © 2019 pop. All rights reserved.
//

import UIKit

class CardAnimator: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
3
}

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView

guard let fromVC = transitionContext.viewController(forKey: .from) as? CardController,
let toVC = transitionContext.viewController(forKey: .to) as? CardDetailViewController,
let cardView = fromVC.selectedView() else { return }

cardView.alpha = 0

let fromViewSnapshot = fromVC.view.snapshotView(afterScreenUpdates: true)!
let cardBackgroundSnapshot = cardView.backgroundImageView.snapshotView(afterScreenUpdates: false)!
let cardTitleSnapshot = cardView.titleLabel.snapshotView(afterScreenUpdates: false)!
let cardSubTitleSnapshot = cardView.subTitleLabel.snapshotView(afterScreenUpdates: false)!

cardBackgroundSnapshot.frame = cardView.convert(cardView.backgroundImageView.frame, to: fromVC.view)
cardTitleSnapshot.frame = cardView.convert(cardView.titleLabel.frame, to: fromVC.view)
cardSubTitleSnapshot.frame = cardView.convert(cardView.subTitleLabel.frame, to: fromVC.view)

containerView.addSubview(fromViewSnapshot)
containerView.addSubview(cardBackgroundSnapshot)
containerView.addSubview(cardTitleSnapshot)
containerView.addSubview(cardSubTitleSnapshot)

let toView: UIView = toVC.view
toView.layoutIfNeeded()

let gradientSnapshot = toVC.gradientView.snapshotView(afterScreenUpdates: true)!
let sheetViewSnapshot = toVC.contentBackgroundView.snapshotView(afterScreenUpdates: true)!
sheetViewSnapshot.frame = CGRect(
origin: CGPoint(x: 0, y: fromVC.view.frame.size.height),
size: toVC.contentBackgroundView.frame.size
)
toView.alpha = 0
gradientSnapshot.alpha = 0
containerView.addSubview(toView)
containerView.addSubview(gradientSnapshot)
containerView.addSubview(sheetViewSnapshot)

UIView.animate(withDuration: 3, animations: {

cardBackgroundSnapshot.frame = self.frame(for: cardBackgroundSnapshot, scaleTo: toVC.backgroundImageView)
cardTitleSnapshot.frame = self.frame(for: cardTitleSnapshot, usingPositionFrom: toVC.numberLabel)
cardSubTitleSnapshot.frame = self.frame(for: cardSubTitleSnapshot, usingPositionFrom: toVC.amountLabel)
sheetViewSnapshot.frame = toVC.contentBackgroundView.frame
fromViewSnapshot.alpha = 0
gradientSnapshot.alpha = 1
}, completion: { _ in
toView.alpha = 1
cardView.alpha = 1
fromViewSnapshot.removeFromSuperview()
cardBackgroundSnapshot.removeFromSuperview()
cardTitleSnapshot.removeFromSuperview()
cardSubTitleSnapshot.removeFromSuperview()
sheetViewSnapshot.removeFromSuperview()
gradientSnapshot.removeFromSuperview()
transitionContext.completeTransition(true)
})
}

func frame(for l: UIView, usingPositionFrom r: UIView) -> CGRect {
CGRect(
origin: CGPoint(x: r.frame.origin.x, y: r.frame.origin.y + statusBarFrameHeightFromWindow(for: l)),
size: l.frame.size
)
}

func frame(for l: UIView, scaleTo r: UIView) -> CGRect {
let h = r.frame.size.width / l.frame.size.width * l.frame.size.height
return CGRect(
origin: CGPoint(x: 0, y: 250 - h),
size: CGSize(width: r.frame.size.width, height: h)
)
}

func statusBarFrameHeightFromWindow(for view: UIView) -> CGFloat {
view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0
}
}

extension UIView {
/// Replacement of `snapshotView` on iOS 10. Fixes the issue of `snapshotView` returning a blank white screen.
func snapshotImageView() -> UIImageView? {
UIGraphicsBeginImageContext(bounds.size)
guard let context = UIGraphicsGetCurrentContext() else {
return nil
}

layer.render(in: context)

let viewImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

return UIImageView(image: viewImage, highlightedImage: viewImage)
}
}
18 changes: 17 additions & 1 deletion Starbucks/CardController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class CardController: UIViewController {
v.textColor = #colorLiteral(red: 0.03921568627, green: 0.3411764706, blue: 0.2352941176, alpha: 1)
return v
}()

var tableView = UITableView()

var cards = [
Expand All @@ -38,6 +37,7 @@ class CardController: UIViewController {
image: UIImage(named: "Seattle")
)
]
var selectedIndexPath: IndexPath?

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
Expand All @@ -46,6 +46,10 @@ class CardController: UIViewController {
}
}

var topbarHeight: CGFloat {
return view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0
}

private func setupView() {
view.addSubview(screenTitleLabel)
view.addSubview(tableView)
Expand All @@ -66,6 +70,7 @@ class CardController: UIViewController {
super.viewDidLoad()
setupTableView()
navigationController?.navigationBar.isHidden = true
navigationController?.delegate = self
}

override func viewWillAppear(_ animated: Bool) {
Expand All @@ -81,6 +86,10 @@ class CardController: UIViewController {
tableView.separatorStyle = .none
tableView.register(CardTableViewCell.self, forCellReuseIdentifier: "cardCell")
}

func selectedView() -> CardTableViewCell? {
selectedIndexPath.flatMap { tableView.cellForRow(at: $0) as? CardTableViewCell }
}
}

extension CardController: UITableViewDataSource {
Expand All @@ -99,9 +108,16 @@ extension CardController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
let card = cards[indexPath.row]
selectedIndexPath = indexPath

let detailViewController = CardDetailViewController()
detailViewController.card = card
navigationController?.pushViewController(detailViewController, animated: true)
}
}

extension CardController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
operation == .push ? CardAnimator() : nil
}
}

0 comments on commit 48c9ed8

Please sign in to comment.