iOS 模态视图
概念: ios开发中,在当前视图上再弹出一个视图(模态视图)例如登陆视图,分享视图,注册等等。
说明: 实现一个简单的多视图应用,视图控制器都会有一个presentViewController方法,用来显示模态窗口,在一些特别的环境下我们尤其愿意使用这种窗口,例如临时呈现一些内容时(登录视图、分享列表视图等),所以今天在这里做一下整理。
OS下的视图控制器都会有一个presentViewController方法,用来显示模态窗口,在一些特别的环境下我们尤其愿意使用这种窗口,例如临时呈现一些内容时(登录视图、分享列表视图等)
一、具体设置和使用
1、弹出模态视图窗口(presentViewController方法)
样例代码为:
GreenViewController *greenViewController = [[GreenViewController alloc] init];
方法1:[self presentModalViewController:greenViewController animated:YES];
方法2:[self presentViewController:greenViewController animated:YES completion:nil];
两种方法都可以弹出模态视图窗口,方法2使用了block封装,如果在动画弹出模块窗口后有其它的操作,可以使用些方法。
2、弹出风格(UIModalPresentationStyle属性)
UIModalPresentationFullScreen充满全屏,对于IOS7以后版本,如果弹出视图控制器的wantsFullScreenLayout设置为YES的,则会填充到状态栏下边,否则不会填充到状态栏之下。
UIModalPresentationPageSheet高度和当前屏幕高度相同,宽度和竖屏模式下屏幕宽度相同,剩余未覆盖区域将会变暗并阻止用户点击,这种弹出模式下,竖屏时跟 UIModalPresentationFullScreen的效果一样,横屏时候两边则会留下变暗的区域。
UIModalPresentationFormSheet高度和宽度均会小于屏幕尺寸,居中显示,四周留下变暗区域。
UIModalPresentationCurrentContext这种模式下,弹出视图控制器的弹出方式和它的父VC的方式相同。
对于iphone或iTouc,只有UIModalPresentationFullScreen一种风格,即使设置成其它风格也没起作用。
3、弹出时的动画风格(UIModalTransitionStyle属性)
弹出模态窗口时,如果我们选择了动画显示,那么我们可以通过modalTransitionStyle属性来设置切入动画的风格。
UIModalTransitionStyleCoverVertical // 底部滑入。
UIModalTransitionStyleFlipHorizontal // 水平翻转。
UIModalTransitionStyleCrossDissolve // 交叉溶解。
UIModalTransitionStylePartialCurl // 翻页。
动画风格不受设备的限制,即不管是iPhone还是iPad都会根据我们指定的风格显示转场效果。
4、回收模块视图窗口(dismissModalViewControllerAnimated方法)
方法一:[self dismissModalViewControllerAnimated:YES]
方法二:[self dismissViewControllerAnimated:YES completion:nil];
注:self为弹出的模块视图控制器
总结:
1、每个视图控制器都可以作为模块窗口来显示,但任何时候应用中如果有一个视图控制器被弹出了,那么再弹其它的视图控制器时都不会有效果。
2、模块窗口的显示必需由其它视图控制器调用presentViewController方法来实现;而模块窗口的隐藏(dismiss)是由自己来调用dismissModalViewControllerAnimated方法来实现。即模块窗口是基于其它视图控制器而显示,但它的回收(dismiss)是基本自身。
3、UIModalPresentationFormSheet风格的模块窗口,如果有输入框,整个视图会根据键盘的显隐自动调整。而且整个模块窗口的大小是可以设置的(greenViewController .view.superview.bounds = CGRectFromString(framePortrait))。如果模块窗口在显示时自动定位光标到文本框,例如:
- (void)viewDidAppear:(BOOL)animated {
[contentTextView becomeFirstResponder];
}
此时模块视图已经根据键盘显示调整到正确的位置,可能由于我们在之前设置模块窗口的bounds
GreenViewController *greenViewController = [[GreenViewController alloc] init];
greenViewController .modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:greenViewController animated:YES];
greenViewController .view.superview.bounds = CGRectFromString(framePortrait);
这样就造成了模块窗口在屏幕中间显示,但键盘的出现会挡住大部分内容。如下图:
5、presentingViewController
presentingViewController是UIViewController的属性,官方文档上这么解释
The view controller that presented this view controller.
大致意思是:A push B ,B的presentingViewController就是A.
视图控制容器(View Controller Container)
像UINavgationController、UITabBarController、UISplitViewController等都属于view controller container这些类的共性是都有一个类型为数组的对象viewControllers属性,用于保存一组视图控制器。view controller container会有自己默认外观。
任何view controller container对象都可以通过viewControllers属性来访问子对象(视图),而子对象也可以通过navigationController, tabbarController, splitViewController, parentViewController找到相应的view controller container。
视图关系
当应用以模态形式(通过presentViewController: animated: completion:推出的视图)显示一个视图时,负责显示的控制器将是view controller container最顶部的视图,而负责推出的视图。如下图:
视图层次关系示意图
A present B,但是B的presentingViewController却是UITabBarController。
若想让B的presentingViewController变成A需要设置definesPresentationContext设置成YES,默认是NO,另外需要将显示的视图的modalPresentationStyle属性设置为UIModalPresentationCurrentContext
代码如下:
navController.modalPresentationStyle =UIModalPresentationCurrentContext;self.definesPresentationContext =YES;
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion;
有这么依据描述:
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.
大致意思是:A push B,那么A就有责任dismiss B,如果在B中调用[self dismissViewControllerAnimated...]就会A中发送dismiss,最终会由有A进行dismiss,相当于在B中执行[self.presentingViewController dismissViewControllerAnimated...]
注:self为弹出的模块视图控制器
此文为转发用于记录总结 ,感谢大神们的总结。