Bright
Bright

Reputation: 5751

How to modally present a view controller without dismissing the parent/first view controller

I'm trying to animate up a UICollectionViewController over an original UIViewController with the original UIViewController blurred as background, however, every time the animation finishes, I can see clearly through the blurred view that the original view controller is dismissed, what do I do to avoid the first UIViewController being dismissed?

Code in the first view controller to present the second:

let VC = storyboard?.instantiateViewController(withIdentifier: "PopoverCollectionVC") as! PopoverCollectionVC
VC.setDataSource(with: .calcDPSItems)
VC.collectionView?.backgroundColor = UIColor.clear
VC.transitioningDelegate = self
self.present(VC, animated: true, completion: nil)

Code in the animator object for custom animation:

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    let containerView = transitionContext.containerView
    let fromView = transitionContext.view(forKey: .from)!
    let toView = transitionContext.view(forKey: .to)!

    if presenting {
        // configure blur
        effectView.frame = fromView.bounds
        containerView.addSubview(effectView)
        // configure collection view
        toView.frame = CGRect(x: 0, y: fromView.frame.height, width: fromView.frame.width, height: fromView.frame.height / 2)
        containerView.addSubview(toView)

        UIView.animateKeyframes(withDuration: duration, delay: 0, options: .calculationModeCubic, animations: {

            UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.6) {
                toView.center.y = fromView.center.y
            }

            UIView.addKeyframe(withRelativeStartTime: 0.1, relativeDuration: 1) {
                self.effectView.effect = UIBlurEffect(style: .dark)
            }

        }) { _ in
            transitionContext.completeTransition(true)
        }
    } else {

        ...
    }

Upvotes: 1

Views: 1186

Answers (2)

Alaeddine
Alaeddine

Reputation: 6212

You need to specify that the modal presentation style will be over the current context :

VC.modalPresentationStyle = .overCurrentContext

Then to get the the presented view you need

// Get the from view from The ViewController because there is a bug in iOS when 
// using some modalPresentationStyle values 
// that causes the viewForKey to returm nil for UITransitionContextFromViewKey 
// www.splinter.com.au/2015/04/17/ios8-view-controller-transiti‌​oning-bug/ 

let fromVC = transitionContext.viewController(forKey: .from) 
let fromView = fromVC?.view

Upvotes: 1

Sean Lintern
Sean Lintern

Reputation: 3141

You should instead take a snapshot of the previous view, then blur than and use it as a background on the new VC.

 let oldView = view_to_copy.snapshotView(afterScreenUpdates: false)

Then blur this, and add as a subview to your collectionView controller.

EDIT:

Just to add if you are using the VC inside something like UITabbar or UINavigationController you may need to snapshot that view to ensure all the UI is inside the snapshot.

Upvotes: 0

Related Questions