iosswiftuiviewcontrollerpresentmodalviewcontroller

Present modal view controller in half size parent controller


I am trying to present modal view controller on other viewcontroller sized to half parent view controller. But it always present in full screen view.

I have created freeform sized View controller in my storyboard with fixed frame size. 320 X 250.

var storyboard = UIStoryboard(name: "Main", bundle: nil)
var pvc = storyboard.instantiateViewControllerWithIdentifier("CustomTableViewController") as ProductsTableViewController
self.presentViewController(pvc, animated: true, completion: nil)

I have tried to set frame.superview and it doesn't help.

Picture example

Please advice.


Solution

  • You can use a UIPresentationController to achieve this.

    For this you let the presenting ViewController implement the UIViewControllerTransitioningDelegate and return your PresentationController for the half sized presentation:

    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        return HalfSizePresentationController(presentedViewController: presented, presenting: presentingViewController)
    }
    

    When presenting you set the presentation style to .Custom and set your transitioning delegate:

    pvc.modalPresentationStyle = .custom
    pvc.transitioningDelegate = self
    

    The presentation controller only returns the frame for your presented view controller:

    class HalfSizePresentationController: UIPresentationController {
        override var frameOfPresentedViewInContainerView: CGRect {
            guard let bounds = containerView?.bounds else { return .zero }
            return CGRect(x: 0, y: bounds.height / 2, width: bounds.width, height: bounds.height / 2)
        }
    }
    

    Here is the working code in its entirety:

    class ViewController: UIViewController, UIViewControllerTransitioningDelegate {
    
        @IBAction func tap(sender: AnyObject) {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let pvc = storyboard.instantiateViewController(withIdentifier: "CustomTableViewController") as! UITableViewController
    
            pvc.modalPresentationStyle = .custom
            pvc.transitioningDelegate = self
            pvc.view.backgroundColor = .red
    
            present(pvc, animated: true)
        }
        
        func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
            return HalfSizePresentationController(presentedViewController: presented, presenting: presentingViewController)
        }
    }
    
    class HalfSizePresentationController: UIPresentationController {
        override var frameOfPresentedViewInContainerView: CGRect {
            guard let bounds = containerView?.bounds else { return .zero }
            return CGRect(x: 0, y: bounds.height / 2, width: bounds.width, height: bounds.height / 2)
        }
    }