UIPopoverPresentationController
来呈现弹出窗口吗?想知道苹果在iOS 8中是否添加了此功能,以尝试为iPad和iPhone创建更统一的表示控制器。不确定是否可以从Beta版提问/回答问题。如果是这种情况,我将删除它。
UIPopoverPresentationController
来呈现弹出窗口吗?想知道苹果在iOS 8中是否添加了此功能,以尝试为iPad和iPhone创建更统一的表示控制器。您可以通过使用UIPopoverPresentationController.delegate
提供的adaptivePresentationStyleForPresentationController:
方法来覆盖默认的自适应行为(在紧凑的水平环境,即iPhone中使用UIModalPresentationFullScreen
),
UIPresentationController
使用此方法来请求要使用的新呈现样式,在这种情况下,简单地返回UIModalPresentationNone
将导致UIPopoverPresentationController
作为弹出窗口而不是全屏进行渲染。
以下是使用故事板中从UIBarButtonItem
到"以模态方式呈现"UIViewController
的转场设置的示例弹出窗口:
class SomeViewController: UIViewController, UIPopoverPresentationControllerDelegate {
// override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) { // swift < 3.0
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "PopoverSegue" {
if let controller = segue.destinationViewController as? UIViewController {
controller.popoverPresentationController.delegate = self
controller.preferredContentSize = CGSize(width: 320, height: 186)
}
}
}
// MARK: UIPopoverPresentationControllerDelegate
//func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!) -> UIModalPresentationStyle { // swift < 3.0
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
// Return no adaptive presentation style, use default presentation behaviour
return .None
}
}
这个技巧在WWDC 2014第214节“iOS8中的视图控制器进阶”(36:30)中提到。
UIPopoverPresentationController
属性:@property(nonatomic,retain)UIPopoverPresentationController *dateTimePopover8;
使用以下方法从UIButton中显示弹出窗口:
- (IBAction)btnSelectDatePressed:(id)sender
{
UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
dateVC.preferredContentSize = CGSizeMake(280,200);
destNav.modalPresentationStyle = UIModalPresentationPopover;
_dateTimePopover8 = destNav.popoverPresentationController;
_dateTimePopover8.delegate = self;
_dateTimePopover8.sourceView = self.view;
_dateTimePopover8.sourceRect = sender.frame;
destNav.navigationBarHidden = YES;
[self presentViewController:destNav animated:YES completion:nil];
}
使用下面的方法从UIBarButtonItem中弹出气泡窗口:
- (IBAction)btnSelectDatePressed:(id)sender
{
UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
dateVC.preferredContentSize = CGSizeMake(280,200);
destNav.modalPresentationStyle = UIModalPresentationPopover;
_dateTimePopover8 = destNav.popoverPresentationController;
_dateTimePopover8.delegate = self;
_dateTimePopover8.sourceView = self.view;
CGRect frame = [[sender valueForKey:@"view"] frame];
frame.origin.y = frame.origin.y+20;
_dateTimePopover8.sourceRect = frame;
destNav.navigationBarHidden = YES;
[self presentViewController:destNav animated:YES completion:nil];
}
- (UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller {
return UIModalPresentationNone;
}
dismissViewControllerAnimated (true, completion: nil)
-(void)hideIOS8PopOver
{
[self dismissViewControllerAnimated:YES completion:nil];
}
SWIFT
使用以下方法从UIButon显示气泡:
func filterBooks(sender: UIButon)
{
let filterVC = FilterDistanceViewController(nibName: "FilterDistanceViewController", bundle: nil)
var filterDistanceViewController = UINavigationController(rootViewController: filterVC)
filterDistanceViewController.preferredContentSize = CGSizeMake(300, 205)
let popoverPresentationViewController = filterDistanceViewController.popoverPresentationController
popoverPresentationViewController?.permittedArrowDirections = .Any
popoverPresentationViewController?.delegate = self
popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
popoverPresentationViewController!.sourceView = self.view;
popoverPresentationViewController!.sourceRect = sender.frame
filterDistanceViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
filterDistanceViewController.navigationBarHidden = true
self.presentViewController(filterDistanceViewController, animated: true, completion: nil)
}
使用以下方法从UIBarButtonItem中呈现气泡窗口:
func filterBooks(sender: UIBarButtonItem)
{
let filterVC = FilterDistanceViewController(nibName: "FilterDistanceViewController", bundle: nil)
var filterDistanceViewController = UINavigationController(rootViewController: filterVC)
filterDistanceViewController.preferredContentSize = CGSizeMake(300, 205)
let popoverPresentationViewController = filterDistanceViewController.popoverPresentationController
popoverPresentationViewController?.permittedArrowDirections = .Any
popoverPresentationViewController?.delegate = self
popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
popoverPresentationViewController!.sourceView = self.view;
var frame:CGRect = sender.valueForKey("view")!.frame
frame.origin.y = frame.origin.y+20
popoverPresentationViewController!.sourceRect = frame
filterDistanceViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
filterDistanceViewController.navigationBarHidden = true
self.presentViewController(filterDistanceViewController, animated: true, completion: nil)
}
在您的视图控制器中也实现此委托方法:
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle{
return .None
}
UIPopoverPresentationControllerDelegate
代理。问题: iPhone上的弹出窗口全屏显示,不遵守preferredContentSize值。
解决方案: 与苹果在UIPopoverPresentationController类参考中建议的相反,在获取到弹出窗口表示控制器并进行配置之后,再呈现视图控制器。
// Get the popover presentation controller and configure it.
//...
// Present the view controller using the popover style.
[self presentViewController:myPopoverViewController animated: YES completion: nil];
请确保按照以下方式实现UIAdaptivePresentationControllerDelegate:
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
如果您不想要全屏弹出窗口
presentationController.delegate
替代 popoverPresentationController.delegate
。- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier compare:@"showPopOver"] == NSOrderedSame) {
UINavigationController * nvc = segue.destinationViewController;
UIPresentationController * pc = nvc.presentationController;
pc.delegate = self;
}
}
#pragma mark == UIPopoverPresentationControllerDelegate ==
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
{
return UIModalPresentationNone;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController * nvc = segue.destinationViewController;
UIPopoverPresentationController * pvc = nvc.popoverPresentationController;
pvc.delegate = self;
}
#pragma mark == UIPopoverPresentationControllerDelegate ==
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
{
return UIModalPresentationNone;
}
但在Xcode 6.1上,这些代码显示了全屏呈现...(nvc.popoverPresentationController为nil)
我怀疑这可能是苹果的一个bug。
UIPopoverPresentationControllerDelegate
协议中覆盖您的弹出窗口的UIModalPresentationStyle
。func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
protocol PopoverPresentationSourceView {}
extension UIBarButtonItem : PopoverPresentationSourceView {}
extension UIView : PopoverPresentationSourceView {}
extension UIPopoverPresentationControllerDelegate where Self : UIViewController {
func present(popover: UIViewController,
from sourceView: PopoverPresentationSourceView,
size: CGSize, arrowDirection: UIPopoverArrowDirection) {
popover.modalPresentationStyle = .popover
popover.preferredContentSize = size
let popoverController = popover.popoverPresentationController
popoverController?.delegate = self
if let aView = sourceView as? UIView {
popoverController?.sourceView = aView
popoverController?.sourceRect = CGRect(x: aView.bounds.midX, y: aView.bounds.midY, width: 0, height: 0)
} else if let barButtonItem = sourceView as? UIBarButtonItem {
popoverController?.barButtonItem = barButtonItem
}
popoverController?.permittedArrowDirections = arrowDirection
present(popover, animated: true, completion: nil)
}
}
现在,您可以从任何实现 UIPopoverPresentationControllerDelegate
的视图控制器中调用 present(popover: from: size: arrowDirection: )
方法。例如:
class YourViewController : UIViewController {
@IBAction func someButtonPressed(_ sender: UIButton) {
let popover = SomeViewController()
present(popover: popover, from: sender, size: CGSize(width: 280, height: 400), arrowDirection: .right)
}
}
extension YourViewController : UIPopoverPresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
}
func adaptivePresentationStyle(for: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle
用这个代替:
func adaptivePresentationStyle(for: UIPresentationController) -> UIModalPresentationStyle
-(void) prepareForSegue: (UIStoryboardSegue * ) segue sender: (id) sender {
// Assuming you've hooked this all up in a Storyboard with a popover presentation style
if ([segue.identifier isEqualToString: @"showPopover"]) {
UINavigationController * destNav = segue.destinationViewController;
pop = destNav.viewControllers.firstObject;
// This is the important part
UIPopoverPresentationController * popPC = destNav.popoverPresentationController;
popPC.delegate = self;
}
}
- (UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller {
return UIModalPresentationNone;
}