Avoid popover adapting to fullscreen in horizontally compact environment

Viewed 160

According to documentation,

In a horizontally compact environment, popovers adapt to the UIModalPresentationOverFullScreen presentation style by default.

See below image. In compact environment, popover appear from bottom and animate to top until it covers the entire screen.

enter image description here

Is it possible to override this behaviour and have the popover only covering certain height of the screen as shown below?

enter image description here

Following code demonstrate the default behaviour of popover adapting to FullScreen presentation style in compact environment.

import UIKit

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .systemBackground
        
        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setImage(UIImage(systemName: "square.grid.2x2.fill"), for: .normal)
        button.addTarget(self, action: #selector(displayPopover), for: .touchUpInside)
        self.view.addSubview(button)
        
        NSLayoutConstraint.activate([
            button.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100),
            button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            button.widthAnchor.constraint(equalToConstant: 40),
            button.heightAnchor.constraint(equalToConstant: 40),
        ])
        
    }
    
    @IBAction func displayPopover(sender: UIButton!) {
        let popoverVC = PopoverViewController()
        popoverVC.preferredContentSize = CGSize(width: 300, height: 200)
        popoverVC.modalPresentationStyle = .popover
        popoverVC.popoverPresentationController?.sourceView = sender
        popoverVC.popoverPresentationController?.permittedArrowDirections = .up
        self.present(popoverVC, animated: true, completion: nil)
    }
    
    
}

class PopoverViewController: UIViewController {
    override func viewDidLoad() {
        self.view.backgroundColor = .systemGray
    }
}

Output:

enter image description here

Thank you ‍♂️

1 Answers

This feature is now available with iOS 15.

Watch WWDC2021 short video

Download WWDC sample project from here

 @IBAction func showImagePicker(_ sender: UIBarButtonItem) {
    
    let imagePicker = UIImagePickerController()
    imagePicker.delegate = self
    imagePicker.modalPresentationStyle = .popover
    if let popover = imagePicker.popoverPresentationController {
        popover.barButtonItem = sender
        
        let sheet = popover.adaptiveSheetPresentationController
        sheet.detents = [.medium(), .large()]
        sheet.largestUndimmedDetentIdentifier = .medium
        sheet.prefersScrollingExpandsWhenScrolledToEdge = false
        sheet.prefersEdgeAttachedInCompactHeight = true 
        sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
    }
    
    present(imagePicker, animated: true, completion: nil)
}
Related