组成如下
首先进入的是一个登录页面,登录页面包含UIImageView、UILabel、UITextField和UIButton组件。页面如下。
首先,应该知道,在整个项目文件中,main.m不用改。AppDelegate监控整个APP运行,是单例,即只被初始化一次。创建一个应用程序,把AppDelegate作为程序代理。在AppDelegate.m的didFinishLaunchingWithOptions{}方法中写代码,代码段如下。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
//初始化,全屏
self.loginVC = [[ViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.loginVC];
//导航控制器,rootviewcontroller是第一个界面,即nav的第一个界面是loginVC
self.window.rootViewController = nav;
//window的第一个界面是nav
[self.window makeKeyAndVisible];
//设置并显示主窗口
return YES;
}
然后在ViewController.m文件的viewDidLoad{ }方法中进行页面布局,在 -(void) viewDidLoad { }中放置初始化代码,但是注意不可以在 -(void) viewDidLoad { }中添加与几何相关的代码,即不可以添加任何关于视图形状的初始化信息。
因为已经添加了导航控制器,所以页面顶端会出现导航栏,然后设置标题以及页面颜色。
然后就是往页面中添加各组件,包含一张图片(UIImageView),两个标签(UILabel),两个文本区域(UITextField),一个按键(UIButton)。
代码段如下。
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"登录";
self.view.backgroundColor = [UIColor whiteColor];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(160, 120, 100, 100)];
//initWithFrame控制位置和尺寸
imageView.image = [UIImage imageNamed:@"123.png"];
[self.view addSubview:imageView];
//把imageView加到视图中
UILabel *userLabel=[[UILabel alloc]initWithFrame:CGRectMake(60, 280, 90, 50)];
userLabel.text=@"用户名:";
[self.view addSubview:userLabel];
UITextField *userField=[[UITextField alloc]init];
userField.frame=CGRectMake(130, 280, 210, 40);
userField.borderStyle = UITextBorderStyleRoundedRect;
userField.layer.borderColor=[UIColor brownColor].CGColor;
userField.layer.borderWidth=1;
userField.layer.cornerRadius=5;
[self.view addSubview:userField];
UILabel *passLabel=[[UILabel alloc]initWithFrame:CGRectMake(60, 350, 90, 50)];
passLabel.text=@"密 码:";
[self.view addSubview:passLabel];
UITextField *passwordField=[[UITextField alloc]init];
passwordField.frame=CGRectMake(130, 350, 210, 40);
passwordField.borderStyle = UITextBorderStyleRoundedRect;
passwordField.secureTextEntry=YES; //输入的字符变成*号
passwordField.clearButtonMode=UITextFieldViewModeAlways; //有“X”键可以清空文本
passwordField.layer.borderColor=[UIColor brownColor].CGColor;
passwordField.layer.borderWidth=1;
passwordField.layer.cornerRadius=5;
[self.view addSubview:passwordField];
UIButton *but=[UIButton buttonWithType:UIButtonTypeRoundedRect];
but.frame=CGRectMake(110, 450, 210, 60);
[but setTitle:@"确认" forState:UIControlStateNormal];
[but addTarget:self action:@selector(jumpToNext) forControlEvents:UIControlEventTouchUpInside];
//按键跳转事件,self指代自身。selector()里面写的是跳转方法,即跳转到jumpToNext()方法。监听“点击事件”,所以是UIControlEventTouchUpInside
[but setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
but.backgroundColor=[UIColor colorWithRed:1.0 green:0.5 blue:0.5 alpha:1.0];
//alpha:透明度
but.titleLabel.font=[UIFont systemFontOfSize:17];//设置按键的字体大小
[self.view addSubview:but];
}
为按键注册一个jumpToNext方法,实现点击按键之后,跳转到tabBar定义的下一界面。
- (void)jumpToNext {
AppDelegate *myAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[myAppDelegate changeToTabBarController]; //调用跳转方法 }
changeToTabBarController方法在AppDelegate.m中定义,
- (void)changeToTabBarController { //自定义的方法,跳转到tabbar。注意要在.h文件中声明
self.tabBarC = [[LSCTabBarViewController alloc] init]; //初始化tabBarC
self.window.rootViewController = self.tabBarC; //设置第一个界面是navtab
}
到这里,登录页面的设置基本完成。
接下来进行tabBar容器的设计,tabBar里包含四个子页面,所以再重新创建五个类,分别是FirstViewController/SecondViewController/ThirdViewController/ForthViewController/LSCTabBarViewController
各子页面的界面分别如下
创建完新类之后,在LSCTabBarViewController.m标签栏容器中的viewDidLoad方法通过addChildViewController语句,将各子界面加入其中,代码如下
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor=[UIColor whiteColor];
FirstViewController *homePage=[[FirstViewController alloc]init];
homePage.tabBarItem.title=@"首页"; //设置标题
homePage.tabBarItem.image=[UIImage imageNamed: @"1.png"]; //设置图片
UINavigationController *firstNav = [[UINavigationController alloc] initWithRootViewController:homePage]; //navigation容器
[self addChildViewController:firstNav]; //将该页面加入到TabBar容器中
SecondViewController *friends=[[SecondViewController alloc]init];
friends.tabBarItem.title=@"联系人";
friends.tabBarItem.image=[UIImage imageNamed:@"2.png"];
UINavigationController *friendsNav=[[UINavigationController alloc]initWithRootViewController:friends];
[self addChildViewController:friendsNav];
ThirdViewController *find=[[ThirdViewController alloc]init];
find.tabBarItem.title=@"发现";
find.tabBarItem.image=[UIImage imageNamed:@"3.png"];
UINavigationController *findNav=[[UINavigationController alloc]initWithRootViewController:find];
[self addChildViewController:findNav];
ForthViewController *i=[[ForthViewController alloc]init];
i.tabBarItem.title=@"我";
i.tabBarItem.image=[UIImage imageNamed:@"4.png"];
UINavigationController *iNav=[[UINavigationController alloc]initWithRootViewController:i];
[self addChildViewController:iNav];
}
然后就是进行各子界面的布局。
在第一子界面(FirstViewController.m),使用到了UITableView组件,因为每个单元格中包含图片,文本和说明文字,所以创建一个First类来方便数据的管理
First.h定义如下
#import <Foundation/Foundation.h>
@interface Firsts : NSObject
@property NSString *photo;
@property NSString *name;
@property NSString *date;
+(Firsts *)initwithPhoto:(NSString *)photo
Name:(NSString *)name
Date:(NSString *)date;
@end
First.m定义如下
#import "Firsts.h"
@implementation Firsts
+(Firsts *)initwithPhoto:(NSString *)photo
Name:(NSString *)name
Date:(NSString *)date{
Firsts *first=[[Firsts alloc]init];
first.photo=photo;
first.name=name;
first.date=date;
return first;
}
@end
这个界面用的是UITableView的普通样式,即UITableViewStylePlain。UITableView里面包含了多个UITableViewCell,即一个表格有多行,每行是一个UITableViewCell,想得到这个效果,用到了UITableViewCell的textLabel(显示内容)、detailTextLabel(显示详情)、imageView属性(显示图片)。[注意tableview的重用机制,还有,注意要在FirstViewController.h文件<>中加入UITableViewDelegate,UITableViewDataSource协议 ] 。
值得注意的是点击各单元格之后,会有选中状态,如下所示。
所以需要在didSelectRowAtIndexPath方法中通过 [ tableView deselectRowAtIndexPath:indexPath animated:YES] 语句,取消表格中各单元格的选中状态。
FirstViewController.m的代码如下
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"首页";
Firsts *first1=[Firsts initwithPhoto:@"photo1.png"
Name:@"Tom"
Date:@"2018.2.3"];
Firsts *first2=[Firsts initwithPhoto:@"photo2.png"
Name:@"Mike"
Date:@"2018.5.23"];
Firsts *first3=[Firsts initwithPhoto:@"photo3.png"
Name:@"Tony"
Date:@"2018.6.3"];
Firsts *first4=[Firsts initwithPhoto:@"photo4.png"
Name:@"Andy"
Date:@"2018.6.17"];
Firsts *first5=[Firsts initwithPhoto:@"photo5.png"
Name:@"Frank"
Date:@"2018.4.13"];
Firsts *first6=[Firsts initwithPhoto:@"photo6.png"
Name:@"Nancy"
Date:@"2018.5.23"];
Firsts *first7=[Firsts initwithPhoto:@"photo7.png"
Name:@"Bruce"
Date:@"2018.4.13"];
_arrayHomes=[[NSMutableArray alloc]initWithObjects:first1,first2,first3,first4,first5,first6,first7, nil] ;
UITableView *homeTable=[[UITableView alloc]initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
[homeTable setRowHeight:80]; //行高
[homeTable setSeparatorColor:[UIColor brownColor]]; //分割线颜色
UIEdgeInsets inset = homeTable.separatorInset;
homeTable.separatorInset = UIEdgeInsetsMake(inset.top, 0, inset.bottom, inset.right); //0表示距左边界的距离
homeTable.delegate=self;
homeTable.dataSource=self;
//设置数据源代理,即从self获取数据
[self.view addSubview:homeTable];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ //这一组有多少行
return _arrayHomes.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:( NSIndexPath *)indexPath{
//每一行显示什么内容,其中,indexPath是对应的第几行
static NSString *identifier = @"identifier";
//identifier。因为一个表中可能存在多种样式的单元格,在这里把相同样式的单元格放在一个集合中,为这个集合加标识符,之后可以通过不同的标识符,选取不同样式的单元格
UITableViewCell *home = [tableView dequeueReusableCellWithIdentifier:identifier];
if (home == nil) {
home = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
} //如果还没有单元格,创建单元格的时候需要使用到标识符identifier。这部分代码体现了UITableViewCell的重用机制
Firsts *f=[_arrayHomes objectAtIndex:indexPath.row];
home.imageView.image=[UIImage imageNamed:f.photo]; //设置图片
home.textLabel.text=f.name; //设置文字
home.detailTextLabel.text=f.date; //设置详细文字
return home;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES]; //取消表格中各行的选中状态
}
至此,第一子界面的布局基本完成。
然后进行第二子界面的布局,在第二子界面(SecondViewController.m),用到了UILabel、UIButton组件。点击“添加”按键,跳转至下一个添加页面(AddViewController.m),添加页面包含UITextView、UIButton组件,在添加页面的文本框中输入信息,再点击“确认添加”按键,可以跳转回第二子界面,并将信息呈现在UILabel上。
SecondViewController.m的代码如下
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.title=@"联系人";
self.friendsLabel=[[UILabel alloc]init];
self.friendsLabel.frame=CGRectMake(70, 210, 280, 220);
UIColor *color=[UIColor colorWithPatternImage:[UIImage imageNamed:@"bg.png"]];
[self.friendsLabel setBackgroundColor:color]; //设置标签的背景图片
self.friendsLabel.textAlignment=NSTextAlignmentCenter;
self.friendsLabel.numberOfLines=0; //支持换行输入
[self.view addSubview:self.friendsLabel];
UIButton *jumpBut=[UIButton buttonWithType:UIButtonTypeRoundedRect];
jumpBut.frame=CGRectMake(130, 500, 150, 60);
[jumpBut setTitle:@"添加" forState:UIControlStateNormal];
[jumpBut addTarget:self action:@selector(add) forControlEvents:UIControlEventTouchUpInside]; //点击事件触发按键跳转至add方法
[jumpBut setBackgroundColor:[UIColor colorWithRed:0.7 green:0.1 blue:0.1 alpha:0.5]];
[jumpBut setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
jumpBut.titleLabel.font=[UIFont systemFontOfSize:17];//设置按键的字体大小
[self.view addSubview:jumpBut];
}
-(void)add{
self.addView=[[AddViewController alloc]init];
self.addView.delegate=self; //指明secondviewcontroller是addviewcontroller的代理
self.addView.hidesBottomBarWhenPushed=YES;//当跳转到下一界面时,可以隐藏底部的bar
[self.navigationController pushViewController:self.addView animated:YES]; //跳转至下一界面
}
-(void)addFriends:(NSString *)friends{ //实现协议定义的方法
self.friendsLabel.text=friends;
}
因为 [ A→B 视图从A跳转到B
B→A B将信息回传给A ]
逆向传递,界面传值中的属性传值无法完成,需要用到界面传值中的代理传值delegate
代理传值就是B将事情委托给A来做,所以在B中定义delegate,在A中实现delegate
创建新的类,命名为AddViewController ,[ 对应于该demo ,A是SecondViewController,B是AddViewController ]在AddViewController.h中声明AddProtocol协议,在B的协议中声明addFriends方法,而addFriends方法的具体实现则是由A定义。
AddViewController.h代码如下
#import <UIKit/UIKit.h>
@protocol AddProtocol <NSObject> //定义协议
-(void)addFriends:(NSString *)friends; //这是协议定义的方法,用于传值,值的类型是字符串
@end
@interface AddViewController : UIViewController
@property id <AddProtocol> delegate; //利用协议来实现代理
-(void)backItem;
@end
AddViewController.m代码如下
- (void)viewDidLoad {
[super viewDidLoad];
self.title=@"添加";
self.view.backgroundColor=[UIColor whiteColor];
self.tx=[[UITextView alloc]init];
self.tx.frame=CGRectMake(60, 200, 300, 140);
self.tx.layer.borderColor=[UIColor blackColor].CGColor;
self.tx.layer.borderWidth=1;
[self.tx setFont:[UIFont fontWithName:@"Arial" size:20]]; //设置文本框里字体的大小
[self.view addSubview:self.tx];
UIButton *back=[UIButton buttonWithType:UIButtonTypeRoundedRect];
back.frame=CGRectMake(130, 450, 150, 60);
[back setTitle:@"确认添加" forState:UIControlStateNormal];
back.layer.borderWidth=1;
[back setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
back.layer.borderColor=[UIColor blackColor].CGColor ;
[back addTarget:self action:@selector(backItem) forControlEvents:UIControlEventTouchUpInside]; //触发点击事件时跳转到backItem方法
[self.view addSubview:back];
}
-(void)backItem{
[self.delegate addFriends:self.tx.text]; //使用协议传递数据
[self.navigationController popViewControllerAnimated:YES]; //返回到上一界面
}
至此,第二子界面的布局基本完成,然后进行第三子界面的布局。在第三子界面(ThirdViewController.m),用到了UILabel组件。ThirdViewController.m代码如下
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"发现";
UILabel *findLabel=[[UILabel alloc]init];
findLabel.frame=CGRectMake(70, 200, 280, 200);
findLabel.layer.borderColor=[UIColor brownColor].CGColor; //标签的边框颜色
findLabel.layer.borderWidth=1; //设置标签的边框
findLabel.text=@"这是发现";
findLabel.textAlignment=NSTextAlignmentCenter; //标签的文本内容居中显示
[self.view addSubview:findLabel];
}
至此,第三子界面的布局基本完成,然后进行第四子界面的布局。在第四子界面(ForthViewController.m),用到了UITableView组件的分组样式,即UITableViewStyleGrouped。一共有三个分组,第一分组有一行,第二分组有四行,第三分组有一行,
ForthViewController.m的代码如下
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
self.title=@"我";
_arraysection=[[NSMutableArray alloc]initWithObjects:@"我的收藏",@"我的订单",@"个人设置",@"关于", nil];
UITableView *iTable=[[UITableView alloc]initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStyleGrouped];
iTable.delegate=self;
iTable.dataSource=self;
[self.view addSubview:iTable];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ //一共有多少个分组
return 3;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ //每个分组有几行
if(section==0){
return 1;
}else if (section==1){
return 4;
}else {
return 1;
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ //给各分组设定不同的高度
if(indexPath.row==0&&indexPath.section==0){
//row==0表示第1行,section==0表示第1个分组,与操作,设置第一个分组第一行的高度为80,其余为50
return 80;
}else{
return 50;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ //为表格填充内容
static NSString *identifier=@"identifier";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell==nil) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];//cell的重用机制
}
cell.backgroundColor=[UIColor whiteColor];
//依次传值
if (indexPath.section==0) {
cell.imageView.image=[UIImage imageNamed:@"i.jpeg"];
cell.textLabel.text=@"AD";
}else if (indexPath.section==1){
// if(indexPath.row==0){
// cell.textLabel.text=@"我的收藏";
// }else if (indexPath.row==1){
// cell.textLabel.text=@"我的订单";
// }else if (indexPath.row==2){
// cell.textLabel.text=@"个人设置";
// }else{
// cell.textLabel.text=@"关于";
// }
// //依次给各cell赋值
cell.textLabel.text=[_arraysection objectAtIndex:indexPath.row];//通过数组传递
}else{
cell.textLabel.text=@"退出登录";
cell.textLabel.textAlignment=NSTextAlignmentCenter; //设置内容居中
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//触发cell响应事件
if(indexPath.section==2){
//Action Sheet功能表单
UIAlertController *action=[UIAlertController alertControllerWithTitle:nil message:@"确认退出?" preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *exit=[UIAlertAction actionWithTitle:@"退出登录" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
[self jumpToLogin]; //点击退出登录后,跳转至jumpToLogin方法
}];
UIAlertAction *cancel=[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
}];
[action addAction:exit]; //为该Action Sheet添加exit按键
[action addAction:cancel]; //为该Action Sheet添加cancel按键
[self presentViewController:action animated:YES completion:nil]; //在界面上显示
}else if (indexPath.section==1){
//依次传值
// if(indexPath.row==0){
// SectionViewController *sectionVC = [[SectionViewController alloc] init];
// sectionVC.titleString = @"我的收藏"; //属性传值方法
// sectionVC.hidesBottomBarWhenPushed = YES; //隐藏底部的标签栏
// [self.navigationController pushViewController:sectionVC animated:YES];
// }else if (indexPath.row==1){
// }else if (indexPath.row==2){
// }else{
// }
SectionViewController *sectionVC = [[SectionViewController alloc] init]; //初始化下一界面
sectionVC.titleString =[_arraysection objectAtIndex:indexPath.row];//属性传值,通过数组传递
sectionVC.hidesBottomBarWhenPushed = YES; //在下一界面隐藏底部的标签栏
[self.navigationController pushViewController:sectionVC animated:YES];//跳转至下一界面
}
[tableView deselectRowAtIndexPath:indexPath animated:YES]; //取消cell的选中状态
}
-(void)jumpToLogin{
AppDelegate *delegate=(AppDelegate *)[UIApplication sharedApplication].delegate;
[delegate changeToLogin];
}
确认对话用到的控件是Action Sheets(功能表单)
点击“我的收藏”等按键,跳转至下一界面(SectionViewController.m),只需要声明一个新的navigationController容器,即创建新的SectionViewController类,改变title属性值就行。
至于下一界面的标题与各按键相对应则用到了界面传值中的属性传值方法
[ 属性传值可以用于A→B(A跳转到B,即顺向传值)]
SectionViewController.m代码如下
- (void)viewDidLoad {
[super viewDidLoad];
self.title = self.titleString;
self.view.backgroundColor=[UIColor whiteColor];
}
至此,基本完成。