避免弹出窗口在水平紧凑的环境中适应全屏

Avoid popover adapting to fullscreen in horizontally compact environment

根据documentation,

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

见下图。在紧凑的环境中,弹出窗口从底部出现并动画到顶部,直到它覆盖整个屏幕。

是否可以覆盖此行为并让弹出窗口仅覆盖屏幕的特定高度,如下所示?

以下代码演示了弹出窗口在紧凑环境中适应全屏显示样式的默认行为。

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
    }
}

输出:

谢谢 ‍♂️

iOS15 现在可以使用此功能。

观看 WWDC2021 短片 video

here

下载 WWDC 示例项目
 @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)
}