RyanTCB
RyanTCB

Reputation: 8224

How to present UIViewController as partial view?

For example, the Music app's "now playing" screen and the Mail app's email composition screen as shown below:

modal example screenshot modal example screenshot

How do I present my views like that? I'm assuming it can't be achieved purely using storyboards alone as all options seem to cover the full screen and not the partial modals as required.

Upvotes: 3

Views: 2493

Answers (2)

marko
marko

Reputation: 2084

This is not the most recent question, so I put this for future use. Hopefully you already made it.

First all you need to do is follow this UIPresentationController guide as is.

Then adjust the presented view controller frame to larger than 2/3 of the screen.

override func containerViewWillLayoutSubviews() {
    presentedView?.frame = frameOfPresentedViewInContainerView
    presentedView?.layer.cornerRadius = 5.0
    presentedView?.layer.masksToBounds = true
}

override func size(forChildContentContainer container: UIContentContainer,
                   withParentContainerSize parentSize: CGSize) -> CGSize {
    switch direction {
        case .left, .right:
            return CGSize(width: parentSize.width*(2.0/3.0), height: parentSize.height)
        case .bottom, .top:
            return CGSize(width: parentSize.width, height: parentSize.height-40.0)
    }
}

override var frameOfPresentedViewInContainerView: CGRect {
    var frame: CGRect = .zero
    frame.size = size(forChildContentContainer: presentedViewController,
                withParentContainerSize: containerView!.bounds.size)

    switch direction {
        case .right:
            frame.origin.x = containerView!.frame.width*(1.0/3.0)
        case .bottom:
            frame.origin.y = 40.0
        default:
            frame.origin = .zero
    }
    return frame
}

Then set the presenting view controller frame during the dimming animation.

    self.presentingFrame = self.presentingViewController.view.frame
    var frame = self.presentingFrame
    frame.size.width -= 40.0
    frame.size.height -= 60.0
    frame.origin.x += 20.0
    frame.origin.y += 30.0

    coordinator.animate(alongsideTransition: { _ in
        self.dimmingView.alpha = 1.0

        self.presentingViewController.view.frame = frame

        self.presentingViewController.view.layer.cornerRadius = 5.0
        self.presentingViewController.view.layer.masksToBounds = true

        UIApplication.shared.statusBarStyle = .lightContent
    })

Don't forget to add the reverse animation too. Result:

result!

Upvotes: 2

ystack
ystack

Reputation: 1805

I'm assuming it can't be achieve purely on storyboards alone...

  • Yes, it can't be.
    Evaluate implementing Custom View Controller Transition Animation to get the transitions right & thereupon it should just be frame & alpha manipulations on the presented view controller's subviews.

Upvotes: 2

Related Questions