如何在 iPhone 上以编程方式在 Swift 中将 UIViewController 呈现为弹出窗口
How to present a UIViewController as a popover in Swift programmatically on iPhone
通常我遵循这里的说明:。
但是,正如其评论中所讨论的,无论 preferredContentSize
还是 sourceRect
,弹出窗口始终是全屏的。
显示弹出窗口的按钮:
func buttonClicked(sender: UIButton!) {
let ac = EmptyViewController() as UIViewController
ac.modalPresentationStyle = .Popover
ac.preferredContentSize = CGSizeMake(200, 200)
let popover = ac.popoverPresentationController
popover?.delegate = self
popover?.permittedArrowDirections = .Any
popover?.sourceView = self.view
popover?.sourceRect = CGRect(x: 100, y: 100, width: 100, height: 100)
presentViewController(ac, animated: true, completion: nil)
}
UIViewController:
import UIKit
class EmptyViewController : UIViewController {
override func viewDidLoad() {
view.backgroundColor = UIColor.redColor()
}
}
I am wondering how to make it a real popover (not full screen size). By the way, as @EI Captain indicated, it works perfectly on iPad but always fullscreen on iPhone.
您不能在 iPhone 中使用此代码在纵向模式下执行此操作...您可以查看 popover section in apple doc here..
这表明:
In iOS 8 and later, you use a UIPopoverPresentationController to present a popover. UIPopoverPresentationController defines a delegate that lets you adjust the display style of your popover content to suit the current display environment. For example, in a horizontally regular environment, your content can display inside a popover; in a horizontally compact environment, your content can display in a full-screen modal view.
正如我所说,如果您可以签入 iPad,您的内容可以显示在弹出框内。
有可能!我不确定从什么时候开始...
在显示为弹出窗口的 UIViewController
的 viewDidLoad
中:
self.preferredContentSize = CGSize(width: myWidth, height: myHeight)
在显示弹出窗口的 UIViewController
中,将 class 设置为 UIPopoverPresentationControllerDelegate
并且:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "Identifier" {
let vc: UIViewController = segue.destination
let pvc = vc.popoverPresentationController
pvc?.delegate = self
return
}
}
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
PS:在storyboard中,不要忘记设置segue kind为"Present As Popover"
就是这样!
对于那些正在寻找如何不使用 segue 的人
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.modalPresentationStyle = .popover
popoverVC.popoverPresentationController?.sourceView = sender
popoverVC.popoverPresentationController?.permittedArrowDirections = .up
popoverVC.popoverPresentationController?.delegate = self
self.present(popoverVC, animated: true, completion: nil)
}
}
extension UIViewController: UIPopoverPresentationControllerDelegate {
public func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
}
class PopoverViewController: UIViewController {
override func viewDidLoad() {
self.view.backgroundColor = .systemGray
self.preferredContentSize = CGSize(width: 300, height: 200)
}
}
结果 iPhone 11 Pro Max
你只需要实现UIPopoverPresentationControllerDelegate
协议的下一个方法:
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
通常我遵循这里的说明:。
但是,正如其评论中所讨论的,无论 preferredContentSize
还是 sourceRect
,弹出窗口始终是全屏的。
显示弹出窗口的按钮:
func buttonClicked(sender: UIButton!) {
let ac = EmptyViewController() as UIViewController
ac.modalPresentationStyle = .Popover
ac.preferredContentSize = CGSizeMake(200, 200)
let popover = ac.popoverPresentationController
popover?.delegate = self
popover?.permittedArrowDirections = .Any
popover?.sourceView = self.view
popover?.sourceRect = CGRect(x: 100, y: 100, width: 100, height: 100)
presentViewController(ac, animated: true, completion: nil)
}
UIViewController:
import UIKit
class EmptyViewController : UIViewController {
override func viewDidLoad() {
view.backgroundColor = UIColor.redColor()
}
}
I am wondering how to make it a real popover (not full screen size). By the way, as @EI Captain indicated, it works perfectly on iPad but always fullscreen on iPhone.
您不能在 iPhone 中使用此代码在纵向模式下执行此操作...您可以查看 popover section in apple doc here..
这表明:
In iOS 8 and later, you use a UIPopoverPresentationController to present a popover. UIPopoverPresentationController defines a delegate that lets you adjust the display style of your popover content to suit the current display environment. For example, in a horizontally regular environment, your content can display inside a popover; in a horizontally compact environment, your content can display in a full-screen modal view.
正如我所说,如果您可以签入 iPad,您的内容可以显示在弹出框内。
有可能!我不确定从什么时候开始...
在显示为弹出窗口的 UIViewController
的 viewDidLoad
中:
self.preferredContentSize = CGSize(width: myWidth, height: myHeight)
在显示弹出窗口的 UIViewController
中,将 class 设置为 UIPopoverPresentationControllerDelegate
并且:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "Identifier" {
let vc: UIViewController = segue.destination
let pvc = vc.popoverPresentationController
pvc?.delegate = self
return
}
}
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
PS:在storyboard中,不要忘记设置segue kind为"Present As Popover"
就是这样!
对于那些正在寻找如何不使用 segue 的人
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.modalPresentationStyle = .popover
popoverVC.popoverPresentationController?.sourceView = sender
popoverVC.popoverPresentationController?.permittedArrowDirections = .up
popoverVC.popoverPresentationController?.delegate = self
self.present(popoverVC, animated: true, completion: nil)
}
}
extension UIViewController: UIPopoverPresentationControllerDelegate {
public func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}
}
class PopoverViewController: UIViewController {
override func viewDidLoad() {
self.view.backgroundColor = .systemGray
self.preferredContentSize = CGSize(width: 300, height: 200)
}
}
结果 iPhone 11 Pro Max
你只需要实现UIPopoverPresentationControllerDelegate
协议的下一个方法:
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .none
}