在iOS开发中,除了使用push方法切换控制器以外,modal也可以实现界面切换,使用modal方便快捷,任何控制器都可以使用modal展示出来,开发中在设置注册,购物车,点赞等小功能的时候可以使用。
首先我们简单了解下ViewController之间的跳转
1、如果在 Storyboard中当前的 ViewController和要跳转的ViewController之间的segue存在,则可以执行performSegueWithIdentifier:sender:这个方法实现跳转。
2、如果目标ViewController存在Storyboard中,但是没有segue。你可以通过UIStoryboard的instantiateViewControllerWithIdentifier:这个方法获取到它,然后再用你想要的方式实现跳转,如:压栈
由于在iOS中并没有专门的模态窗口类,模态窗口(modal)在iOS中只是视图控制器显示的一种方式,模态窗口不依赖于控制器容器(比如UITabBarController和UINavigationController),通常用于显示独立的内容,在模态窗口显示的时其他视图的内容无法进行操作,通俗的讲,modal最常用的场景,新的场景完全盖住了旧的那个。用户无法再与上一个场景交互,除非他们先关闭这个场景。
modal的基本使用方法有如下两种:
//使用modal弹出控制器
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
//关闭当初Modal出来的控制器
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion;
系统自带的modal动画效果是从下往上的,但是我们可以通过modalTransitionStyle属性,实现其他效果。
typedef enum {
UIModalTransitionStyleCoverVertical = 0,
UIModalTransitionStyleFlipHorizontal,
UIModalTransitionStyleCrossDissolve,
UIModalTransitionStylePartialCurl,
} UIModalTransitionStyle;
我们可以通过UIModalPresentationStyle属性定义弹出风格
UIModalPresentationFullScreen充满全屏,对于IOS7以后版本,如果弹出视图控制器的wantsFullScreenLayout设置为YES的,则会填充到状态栏下边,否则不会填充到状态栏之下。
UIModalPresentationPageSheet高度和当前屏幕高度相同,宽度和竖屏模式下屏幕宽度相同,剩余未覆盖区域将会变暗并阻止用户点击,这种弹出模式下,竖屏时跟 UIModalPresentationFullScreen的效果一样,横屏时候两边则会留下变暗的区域。
UIModalPresentationFormSheet高度和宽度均会小于屏幕尺寸,居中显示,四周留下变暗区域。
UIModalPresentationCurrentContext这种模式下,弹出视图控制器的弹出方式和它的父VC的方式相同。
同样,我们也可以自定义跳转动画效果,代码如下。
CATransition *animation = [CATransition animation];
[animation setDuration:0.3];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[myViewController.view layer] addAnimation:animation forKey:@"SwitchToView"];
[self presentModalViewController:myViewController animated:YES];
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);
这样模块窗口会在屏幕中间显示,我们可以输入相应内容。
在开发中会遇到这种情况,要先用presentModalViewController到登录界面,在登录界面在pushViewController到注册界面,push不过去
//先使用modal,present出一个登陆界面
LoginViewController *login = [[LoginViewController alloc]init];
[self.navigationController presentModalViewController:login animated:YES];
//从登陆界面push到注册界面注册界面没有效果
RegisterViewController *registerViewConotroller = [[RegisterViewController alloc]init];
[self.navigationController pushViewController:registerViewConotroller animated:YES];
此时就要在push之前自定义UINavigationController,将其跟控制器设置为registerViewConotroller,代码如下:
LoginViewController *login = [[LoginViewController alloc]init];
UINavigationController *Nav = [[UINavigationController alloc]initWithRootViewController:login];
[self.navigationController presentModalViewController:Nav animated:YES];
,