十、ios 模态窗口[实例]
一、模态窗口概念
对话框一般分为两种类型:模态类型( modal )与非模态类型( modeless )。所谓模态对话框,就是指除非采取有效的关闭手段,用户的鼠标焦点或者输入光标将一直停留在其上的对话框。非模态对话框则不会强制此种特性,用户可以在当前对话框以及其他窗口间进行切换。
弹出模态视图窗口(presentViewController方法)
样例代码为:
MyViewController *myViewController = [[MyViewController alloc] init]; (MyViewController 自己创建的UI view controller界面)
方法1:[self presentModalViewController:myViewController animated:YES];
方法2:[self presentViewController:myViewController animated:YES completion:nil];
两种方法都可以弹出模态视图窗口,方法2使用了block封装,如果在动画弹出模块窗口后有其它的操作,可以使用此方法。
二、创建 模态窗口实例
2.1 新建Empty Application(九、UINavigationController切换视图实例中有创建空工程的方法)
2.2 创建三个View Controller页面,分别命名为KCMainViewController、MyLoginViewController、MyselfViewController.h
2.3 在AppDelegate.m 的函数
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中添加如下代码 将kcMainViewController作为主界面
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
KCMainViewController *kcMainViewController = [[KCMainViewController alloc]init];
self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
//两种设置背景色方法
//self.window.backgroundColor = [UIColor colorWithRed:249/255.0 green:249/255.0 blue:249/255.0 alpha:1];
self.window.backgroundColor = [UIColor whiteColor];//白色
//设置全局导航条风格和颜色
[[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:23/255.0 green:180/255.0 blue:237/255.0 alpha:1]]; [[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
self.window.rootViewController = kcMainViewController;
[self.window makeKeyAndVisible];
return YES;
}
2.4 在MyLoginViewController界面动态生成两个输入框和一个登录按钮作为登录界面
添加如下代码到MyLoginViewController.m
@interface MyLoginViewController (){
UITextField *_txtUserNmae;
UITextField *_txtPassword;
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
[self addLoginFrom];
}
-(void)addLoginFrom{
//用户名标签
UILabel *lbUserName = [[UILabel alloc]initWithFrame:CGRectMake(50, 100, 150, 30)];
lbUserName.text = @"用户名:";
[self.view addSubview:lbUserName];
//用户名输入框
_txtUserNmae = [[UITextField alloc]initWithFrame:CGRectMake(120, 150, 150,30)];
_txtUserNmae.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:_txtUserNmae];
//密码标签
UILabel *lbPassword = [[UILabel alloc]initWithFrame:CGRectMake(50, 200, 100, 30)];
lbPassword.text = @"密码:" ;
[self.view addSubview:lbPassword];
//密码输入框
_txtPassword = [[UITextField alloc]initWithFrame:CGRectMake(120, 200, 150, 30)];
_txtPassword.secureTextEntry = YES;
_txtPassword.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:_txtPassword];
//登录按钮
UIButton *btnLogin = [UIButton buttonWithType:UIButtonTypeSystem];
btnLogin.frame = CGRectMake(70, 270, 80, 30);
[btnLogin setTitle:@"登录" forState:UIControlStateNormal];
[self.view addSubview:btnLogin];
[btnLogin addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
//取消
UIButton *btnCancel = [UIButton buttonWithType:UIButtonTypeSystem];
btnCancel.frame = CGRectMake(170, 270, 80, 30);
[btnCancel setTitle:@"取消" forState:UIControlStateNormal];
[self.view addSubview:btnCancel];
[btnCancel addTarget:self action:@selector(cancel) forControlEvents:UIControlEventTouchUpInside];
}
-(void)login{
if([_txtUserNmae.text isEqualToString:@"jinxia"] &&[_txtPassword.text isEqualToString:@"123"])
{
[self dismissViewControllerAnimated:YES completion:nil];
}
else
{
//登录失败弹出提示信息
UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"系统信息" message:@"用户名或密码错误,请重新输入!" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil];
[alertView show];
}
}
#pragma mark 点击取消
-(void)cancel{
[self dismissViewControllerAnimated:YES completion:nil];
}
2.5 定义主界面视图控制器KCMainViewController,在左上角放一个登录按钮用于弹出登录界面 右上角放一个按钮用于登录后显示个人信息
#import "KCMainViewController.h"
#import "MyLoginViewController.h"
#import "MyselfViewController.h"
@interface KCMainViewController (){
UILabel *_loginInfo;
UIBarButtonItem *_loginButton;
UIBarButtonItem *_meButton;
BOOL _isLogon;
}
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self addNavigationBar];
[self addLoginInfo];
}
#pragma mark 添加信息显示
-(void)addLoginInfo{
_loginInfo =[[UILabel alloc]initWithFrame:CGRectMake(0, 100,320 ,30)];
_loginInfo.textAlignment=NSTextAlignmentCenter;
[self.view addSubview:_loginInfo];
}
-(void)addNavigationBar{
//创建导航
UINavigationBar *navigationBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, 320, 44+20)];
[self.view addSubview:navigationBar];
//创建导航控件
UINavigationItem *navigationItem = [[UINavigationItem alloc]initWithTitle:@"分享"];
//另外一种创建方法
/*UIButton* backButton = [[UIButton alloc] init];
[backButton setImage:nil forState:UIControlStateSelected];
[backButton setTitle:@"登录" forState:UIControlStateNormal];
[backButton addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* leftButton = [[UIBarButtonItem alloc] initWithCustomView:backButton];*/
_loginButton = [[UIBarButtonItem alloc]initWithTitle:@"登录" style:UIBarButtonItemStyleDone target:self action:@selector(login)];
navigationItem.leftBarButtonItem = _loginButton;
//左侧添加导航
_meButton=[[UIBarButtonItem alloc]initWithTitle:@"My" style:UIBarButtonItemStyleDone target:self action:@selector(showInfo)];
_meButton.enabled=NO;
navigationItem.rightBarButtonItem=_meButton;
[navigationBar pushNavigationItem:navigationItem animated:NO];
}
-(void)login{
if(!_isLogon)
{
MyLoginViewController *loginController = [[MyLoginViewController alloc]init];
loginController.delegate = self;
[self presentViewController:loginController animated:YES completion:nil];
}
else
{
//如果登录之后则处理注销的情况
//注意当前视图控制器必须实现UIActionSheet代理才能进行操作
UIActionSheet *actionSheet=[[UIActionSheet alloc]initWithTitle:@"系统信息" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"注销" otherButtonTitles: nil];
[actionSheet showInView:self.view];
}
}
#pragma mark 点击查看我的信息
-(void)showInfo{
if (_isLogon) {
MyselfViewController *meController=[[MyselfViewController alloc]init];
[self presentViewController:meController animated:YES completion:nil];
}
}
#pragma mark 实现注销方法
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex == 0){
_isLogon = NO;
_loginButton.title = @"登录";
_loginInfo.text = @"";
_meButton.enabled=NO;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
2.6 添加展示用户信息的控制器视图MyselfViewController
在.h中添加
@property (nonatomic,copy) NSString *userInfo;
在.m中添加
#import "MyselfViewController.h"
@interface MyselfViewController (){
UILabel *_lbUserInfo;
}
@end
@implementation MyselfViewController
- (void)viewDidLoad {
[super viewDidLoad];
//信息显示标签
_lbUserInfo =[[UILabel alloc]initWithFrame:CGRectMake(0, 100,320 ,30)];
_lbUserInfo.textAlignment=NSTextAlignmentCenter;
_lbUserInfo.textColor=[UIColor colorWithRed:23/255.0 green:180/255.0 blue:237/255.0 alpha:1];
[self.view addSubview:_lbUserInfo];
//关闭按钮
UIButton *btnClose=[UIButton buttonWithType:UIButtonTypeSystem];
btnClose.frame=CGRectMake(110, 200, 100, 30);
[btnClose setTitle:@"关闭" forState:UIControlStateNormal];
[btnClose addTarget:self action:@selector(close) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnClose];
//设置传值信息
_lbUserInfo.text= _userInfo;
}
#pragma mark 关闭
-(void)close{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
2.7 建立页面直接的数据传递
假设用户名输入“jinxia”,密码输入“123”就认为登录成功,否则登录失败。同时登录成功之后在主视图控制器中显示用户名并且登录按钮变成“注销”。要实现这个功能主要的问题就是如何把登录后的用户名信息传递到主界面?由此引出一个问题:多视图参数传递。
在iOS开发中常用的参数传递有以下几种方法:
- 采用代理模式
- 采用iOS消息机制
- 通过NSDefault存储(或者文件、数据库存储等)
- 通过AppDelegate定义全局变量(或者使用UIApplication、定义一个单例类等)
- 通过控制器属性传递
在KCMainViewController和MyLoginViewController之间采用第一种方式进行数据传递,这在iOS开发中也是最常见的一种多视图传参方式。使用代理方式传递参数的步骤如下:
1.定义协议,协议中定义好传参时所需要的方法
2.目标视图控制器定义一个代理对象
3.源视图控制器实现协议并在初始化目标控制器时指定目标控制器的代理为其自身
4.需要传参的时候在目标窗口调用代理的协议方法
具体代码添加情况如下
在KCMainViewController.h的interface上方添加
//定义协议
@protocol KCMainDelegate
-(void)showUserInfoWithUserName:(NSString *)userName;
@end
在MyLoginViewController.h中添加如下代码
#import <UIKit/UIKit.h>
@protocol KCMainDelegate;
@interface MyLoginViewController : UIViewController
//定义一个代理对象
@property(nonatomic,strong)id <KCMainDelegate> delegate;
@end
在KCMainViewController.m的中添加
#pragma mark 实现代理方法
-(void)showUserInfoWithUserName:(NSString *)userName{
_isLogon=YES;
//显示登录用户的信息
_loginInfo.text=[NSString stringWithFormat:@"Hello,%@!",userName];
//登录按钮内容改为“注销”
_loginButton.title=@"注销";
_meButton.enabled=YES;
}
//指定目标控制器的代理为其自身
在-(void)login中MyLoginViewController *loginController = [[MyLoginViewController alloc]init];下方添加
loginController.delegate = self;
//在目标窗口调用代理的协议方法
在MyLoginViewController.m中-(void)login的[self dismissViewControllerAnimated:YES completion:nil];上方添加
//调用代理方法传参
[self.delegate showUserInfoWithUserName:_txtUserNmae.text];
至此两个界面的传参完成,现在点击登录可以跳转到登录界面,如果用户名、密码输入正确可以回传参数到主界面中(不正确则给出提示),同时修改主界面按钮显示内容。如果已经登录则点击注销会弹出提示,点击确定注销则会注销登录信息。在代码中还用到了UIActionSheet和UIAlert,这两个控件其实也是模态窗口,只是没有铺满全屏。
KCMainViewController和MyselfViewController之间采用第五种方式进行数据传递
在KCMainViewController.m的-(void)showInfo中的[self presentViewController:meController animated:YES completion:nil]; 上方添加
meController.userInfo=_loginInfo.text;
三、选择: File -> Save
最后在 xCode 选择 Build and then Running
模拟器效果图
本文源于网上,经过本人修改和测试。原地址 http://www.cnblogs.com/kenshincui/p/3940746.html#ModalWindow
代码下载:https://github.com/beike/ModalwindowDemo.git