Presenting UIViewController on half of screen on iOS 14

716 Views Asked by At

I've been using the following code snippet to achieve the effect of presenting a view controller on only half of the screen:

func showPlayerView() {
    let controller = storyboard!.instantiateViewController(withIdentifier: "playerViewController") as! PlayerViewController
    controller.player = self.player
    controller.providesPresentationContextTransitionStyle = true
    controller.definesPresentationContext = true
    controller.transitioningDelegate = self
    
    self.present(controller, animated: true, completion: nil)
}

extension ViewController : UIViewControllerTransitioningDelegate
{
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        if presented is PlayerViewController {
            return HalfSizePresentationController(presentedViewController: presented, presenting: presenting)
        }
        return nil
    }
    
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return animator
    }
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return animator
    }
}

class HalfSizePresentationController : UIPresentationController {
    override var frameOfPresentedViewInContainerView: CGRect
    {
        get {
            let height: CGFloat = 200
            return CGRect(x: 0, y: UIScreen.main.bounds.height - height, width: UIScreen.main.bounds.width, height: 200)
        }
    }
}

This used to work on tvOS 13, but now since tvOS 14 what I get is this: Bad animation

Any idea how this can be achieved on iOS 14?

1

There are 1 best solutions below

0
On

Apparently the issue was with tvOS 11 setting the default transition style to something different than what it used to be.

I was able to fix this by adding the following line:

controller.modalPresentationStyle = .custom

Just before calling self.present(controller, animated: true, completion: nil).

However, this introduced a new problem that caused the original ViewController to disappear after the animation was over, as discussed here: Presented view controller disappears after animation using custom UIViewController animations

Ended up solving it by adding the following lines to my UIPresentationController:

override func dismissalTransitionDidEnd(_ completed: Bool) {
    if let window = UIApplication.shared.keyWindow {
        if let viewController = window.rootViewController {
            window.addSubview(viewController.view)
        }
    }
}