鉴于这个常见的问题没有完整、确定的答案,我将在这里提出并回答。
通常,我们需要展示一个 UIViewController
,使其不覆盖整个屏幕,如下图所示。
苹果提供了几个类似的 UIViewController
,例如 UIAlertView
,Twitter 或 Facebook 分享视图控制器等。
我们如何为自定义控制器实现此效果?
鉴于这个常见的问题没有完整、确定的答案,我将在这里提出并回答。
通常,我们需要展示一个 UIViewController
,使其不覆盖整个屏幕,如下图所示。
苹果提供了几个类似的 UIViewController
,例如 UIAlertView
,Twitter 或 Facebook 分享视图控制器等。
我们如何为自定义控制器实现此效果?
注意: 这个解决方案在iOS 8中已经失效了,我会尽快发布新的解决方案。
这里我将用storyboard来回答,但也可以不用storyboard实现。
初始化: 在storyboard中创建两个UIViewController
。
FirstViewController
,另一个是弹出窗口SecondViewController
。
模态Segue: 在FirstViewController
中放置一个UIButton
,并为此UIButton
创建一个指向SecondViewController
的模态Segue。
设置透明背景: 现在选择SecondViewController
的UIView
(默认与UIViewController
一起创建),将其背景颜色更改为透明色。
设置背景变暗: 在SecondViewController
中添加一个UIImageView
,覆盖整个屏幕,并将其图像设置为某种降低透明度的半透明图像。您可以从这里获取样本:UIAlertView
背景图像
显示设计: 现在添加一个UIView
,并制作任何想要展示的设计。这是我的storyboard的截图
SecondViewController
来请求用户名和密码。重要提示: 现在是最关键的步骤。我们希望SecondViewController
不完全遮挡FirstViewController
。我们已经设置为透明色,但这还不够。默认情况下,在模态呈现后会添加黑色背景,因此我们必须在FirstViewController
的viewDidLoad
中添加一行代码。您也可以在其他地方添加它,但应该在Segue之前运行。
[self setModalPresentationStyle:UIModalPresentationCurrentContext];
取消显示: 何时取消显示取决于您的用例。由于这是模态呈现,因此我们执行模态呈现所需的操作即可取消显示:
[self dismissViewControllerAnimated:YES completion:Nil];
就这些了.....
欢迎提出任何建议和评论。
演示 : 您可以从这里获取演示源代码:Popup Demo
新的: 某人在这个概念上做得非常好:MZFormSheetController
新的: 我找到了另一个代码来实现这种功能:KLCPopup
iOS 8更新:我使这种方法适用于iOS
可以在prepareForSegue代理方法中像这样使用该方法。
+ (void)setPresentationStyleForSelfController:(UIViewController *)selfController presentingController:(UIViewController *)presentingController { if (iOSVersion >= 8.0) { presentingController.providesPresentationContextTransitionStyle = YES; presentingController.definesPresentationContext = YES; [presentingController setModalPresentationStyle:UIModalPresentationOverCurrentContext]; } else { [selfController setModalPresentationStyle:UIModalPresentationCurrentContext]; [selfController.navigationController setModalPresentationStyle:UIModalPresentationCurrentContext]; } }
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { PopUpViewController *popup = segue.destinationViewController; [self setPresentationStyleForSelfController:self presentingController:popup] }
[self setModalPresentationStyle:UIModalPresentationCurrentContext];
似乎会破坏模态转换动画(例如 UIModalTransitionStyleCrossDissolve
),当呈现第二个视图控制器时,它只是弹出而没有动画。有什么想法如何解决这个问题吗? - filwag[self setModalPresentationStyle:UIModalPresentationCurrentContext];
单独使用是无效的。必须像您演示项目中展示的那样同时使用[self.navigationController setModalPresentationStyle:UIModalPresentationCurrentContext];
。 - Vasu在您要作为模态弹窗的视图控制器上,将根UIView的背景颜色设置为透明。 提示:不要使用根UIView作为您的弹窗。添加一个较小的新UIView来作为您的弹窗。
创建一个Segue到拥有您的弹窗的视图控制器。选择“Present Modally”。
选择Segue并将Presentation更改为“Over Current Context”:
选择您的弹窗所在的ViewController场景。在Attributes Inspector下,View Controller部分中,将Presentation设置为“Over Current Context”:
任何一种方法都可以。就是这样!
你可以在Interface Builder中完成此操作。
请放心使用我的表单表格控制器MZFormSheetController,在示例项目中有许多关于如何呈现模态视图控制器以不覆盖整个窗口并具有许多呈现/转换样式的示例。
您还可以尝试最新版本的MZFormSheetController,名为MZFormSheetPresentationController,它具有更多功能。
// init YourViewController
let contentVC = ...
// Init popup view controller with content is your content view controller
let popupVC = PopupViewController(contentController: contentVC, popupWidth: 100, popupHeight: 200)
// show it by call present(_ , animated:) method from a current UIViewController
present(popupVC, animated: true)
在背景上放置UIImageView不是最好的选择。在我的情况下,我在控制器视图上添加了另外两个视图。第一个视图背景使用[UIColor clearColor]
,第二个视图背景使用希望透明的颜色(在我的情况下是灰色)。请注意顺序很重要。然后为第二个视图设置alpha值为0.5(alpha值范围为0到1)。将这些行添加到prepareForSegue
中。
infoVC.providesPresentationContextTransitionStyle = YES;
infoVC.definesPresentationContext = YES;
您可以这样做将任何其他子视图添加到视图控制器中。 首先,将要作为子视图添加的ViewController的状态栏设置为None,以便您可以将其调整为任何大小。然后在Present View Controller中创建一个按钮和一个用于按钮点击的方法。在该方法中:
- (IBAction)btnLogin:(id)sender {
SubView *sub = [[SubView alloc] initWithNibName:@"SubView" bundle:nil];
sub.view.frame = CGRectMake(20, 100, sub.view.frame.size.width, sub.view.frame.size.height);
[self.view addSubview:sub.view];
}