         appIconContainerView.layer.add(animation, forKey: "cornerRadius")
     }
     
-    func snapshotImageForZoomingAppIcons(from viewController: SpringBoardViewController) -> UIImage {
+    // MARK: - Setting up views
+    
+    private func setupAppCollectionContainerView(for bounds: CGRect, appIconFrame: CGRect) -> (UIView, UIView) {
+        let appCollectionContainerView = UIView()
+        // Move the anchor point to the center of the app that is being launched so that
+        // the zoom animation will look like we are going into that app
+        appCollectionContainerView.layer.anchorPoint = CGPoint(x: appIconFrame.midX / bounds.maxX,
+                                                               y: appIconFrame.midY / bounds.maxY)
+        appCollectionContainerView.frame = bounds
+        
+        let dockViewSnapshot = SpringBoardDockView()
+        let currentDockViewFrame = springBoardViewController.dockView.frame
+        appCollectionContainerView.addSubview(dockViewSnapshot)
+        dockViewSnapshot.frame = CGRect(x: currentDockViewFrame.origin.x, y: currentDockViewFrame.origin.y,
+                                        width: appCollectionContainerView.bounds.width, height: currentDockViewFrame.height)
+        dockViewSnapshot.autoresizingMask = [.flexibleWidth, .flexibleTopMargin]
+        
+        let appCollectionSnapshotView = UIImageView()
+        appCollectionContainerView.addSubview(appCollectionSnapshotView)
+        appCollectionSnapshotView.image = snapshotImageForZoomingAppIcons(from: springBoardViewController)
+        appCollectionSnapshotView.frame = appCollectionContainerView.bounds
+        appCollectionSnapshotView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+
+        return (appCollectionContainerView, appCollectionSnapshotView)
+    }
+    
+    private func setupAppIconContainerView(for appIconFrame: CGRect, with appInitialView: UIView) -> (UIView, UIView) {
+        // TODO: true?
+        let appInitialViewSnapshot = appInitialView.snapshotView(afterScreenUpdates: true)!
+
+        let appIconContainerView = UIView(frame: appIconFrame)
+        
+        let appIconImageView = appIconButton.snapshotView(afterScreenUpdates: false)!
+        appIconContainerView.addSubview(appIconImageView)
+        appIconImageView.frame = appIconContainerView.bounds
+        appIconImageView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
+        
+        appIconContainerView.addSubview(appInitialViewSnapshot)
+        appInitialViewSnapshot.frame = appIconContainerView.bounds
+        appInitialViewSnapshot.autoresizingMask = [.flexibleHeight, .flexibleWidth]
+
+        return (appIconContainerView, appInitialViewSnapshot)
+    }
+    
+    // MARK: - Creating snapshots
+    
+    private func snapshotImageForZoomingAppIcons(from viewController: SpringBoardViewController) -> UIImage {
         let springBoardView = viewController.containerView
         // Slightly increase the scale here so that when the image is zoomed things still look sharp
         let imageScale = springBoardView.window!.screen.scale * 2

    var startingCornerRadius = CGFloat(14)
    var otherAppZoomScale = CGFloat(5)
    var wallpaperZoomScale = CGFloat(1.5)
    var duration = TimeInterval(0.3)
    
    init(appIconButton: UIButton, springBoardViewController: SpringBoardViewController, isPresenting: Bool) {
        self.appIconButton = appIconButton

    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        let toViewController = transitionContext.viewController(forKey: .to)!
        let fromViewController = transitionContext.viewController(forKey: .from)!
        let toView = toViewController.view!
        
        let finalFrame = transitionContext.finalFrame(for: fromViewController)
        let appInitialView = isPresenting ? toView : fromViewController.view!
        let appIconFrame = appIconButton.convert(appIconButton.frame, to: nil)
        
        let wallpaperSnapshotView = springBoardViewController.wallpaperView.snapshotView(afterScreenUpdates: false)!
        containerView.addSubview(wallpaperSnapshotView)
        
        let (appCollectionContainerView, appCollectionSnapshotView) = setupAppCollectionContainerView(for: containerView.bounds, appIconFrame: appIconFrame)
        containerView.addSubview(appCollectionContainerView)
        
        // TODO: can just set this frame afterwards?
        let (appIconContainerView, appInitialViewSnapshot) = setupAppIconContainerView(for: appIconFrame, with: appInitialView)
        containerView.addSubview(appIconContainerView)

        // Initialize frame values
        appCollectionContainerView.frame = containerView.bounds
        wallpaperSnapshotView.frame = containerView.bounds

        // Setup a block used for updating views for animation states
        let updateViewsForAnimation: (Bool) -> () = { isLaunched in
            appCollectionContainerView.transform = isLaunched ? CGAffineTransform(scaleX: self.otherAppZoomScale, y: self.otherAppZoomScale) : CGAffineTransform.identity
            wallpaperSnapshotView.transform = isLaunched ? CGAffineTransform(scaleX: self.wallpaperZoomScale, y: self.wallpaperZoomScale) : CGAffineTransform.identity
            appIconContainerView.frame = isLaunched ? finalFrame : appIconFrame
            appCollectionSnapshotView.alpha = isLaunched ? 0 : 1
            appInitialViewSnapshot.alpha = isLaunched ? 2 : 0
        }
        
        // Initialize views for the current state (not the end animated state)
        updateViewsForAnimation(!isPresenting)
        
        // Build animation
        let curveProvider = UISpringTimingParameters(dampingRatio: 1)
        let animator = UIViewPropertyAnimator(duration: duration, timingParameters: curveProvider)
        animator.addAnimations {
            updateViewsForAnimation(self.isPresenting)
        }
        animator.addCompletion { (position) in
            appIconContainerView.removeFromSuperview()
            wallpaperSnapshotView.removeFromSuperview()
            appCollectionContainerView.removeFromSuperview()
            
            if self.isPresenting {
                containerView.addSubview(toView)
            }
            
            transitionContext.completeTransition(position == .end && !transitionContext.transitionWasCancelled)
        }
        animator.startAnimation()
        
        // Animate corner radius seprately since CALayer properties can't be animated
