UIPopoverPresentationController
を使用して、iPhoneでポップオーバーを表示できるかどうかを知っていますか? iPadおよびiPhone用のより統一されたプレゼンテーションコントローラーを作成しようとして、AppleがiOS 8にこの機能を追加したかどうか疑問に思いました。
ベータ版からの質問/回答に問題がないかどうかはわかりません。その場合は削除します。
adaptivePresentationStyleForPresentationController:
で利用できるUIPopoverPresentationController.delegate
メソッドを使用して、デフォルトの適応動作(コンパクトな水平環境、つまりiPhoneのUIModalPresentationFullScreen
)をオーバーライドできます。
UIPresentationController
はこのメソッドを使用して、使用する新しいプレゼンテーションスタイルを要求します。この場合、UIModalPresentationNone
を返すだけで、UIPopoverPresentationController
がフルスクリーンではなくポップオーバーとしてレンダリングされます。
ストーリーボードでUIBarButtonItem
から "present modally" a 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 "View Controller Advancement in iOS8" (36:30)で言及されました
誰かがコードだけでポップオーバーを表示したい場合は、次のアプローチを使用できます。
目的-C
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];
}
View Controllerにもこのデリゲートメソッドを実装します:
- (UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller {
return UIModalPresentationNone;
}
このポップオーバーを閉じるには、View Controllerを閉じます。以下は、View Controllerを閉じるためのコードです。
-(void)hideIOS8PopOver
{
[self dismissViewControllerAnimated:YES completion:nil];
}
スイフト
次のメソッドを使用して、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)
}
View Controllerにもこのデリゲートメソッドを実装します:
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle{
return .None
}
デリゲートUIPopoverPresentationControllerDelegate
を.h/.m/.Swiftファイルに追加してください
問題: iPhoneポップオーバーはフルスクリーンを表示し、preferredContentSize値を尊重しません。
SOLUTION: UIPopoverPresentationController ClassリファレンスでAppleが提案するものに反して、View Controllerafterを提示するポップオーバープレゼンテーションコントローラーへの参照と構成。
// Get the popover presentation controller and configure it.
//...
// Present the view controller using the popover style.
[self presentViewController:myPopoverViewController animated: YES completion: nil];
回避策を見つけました。
Xcode6.1では、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;
}
WWDC 2014「iOS8のコントローラーの進歩の表示」では、以下のコードがiPhoneでポップオーバーを表示できます。
- (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では、これらのコードはFullScreenプレゼンテーションを表示します...(nvc.popoverPresentationControllerはnilです)
Appleのバグではないかと思う。
必ず実装してください IAdaptivePresentationControllerDelegate
このような:
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
フルスクリーンポップオーバーが必要ない場合
IOS 8.3以降では、UIPopoverPresentationControllerDelegate
プロトコルで次の構文を使用して、ポップアップのUIModalPresentationStyle
をオーバーライドします。
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
これら2つのメソッドをWEBVIEWクラスに追加します。そして追加
-(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;
}