本文和《【Android】底部标签页,Tabhost置底》(点击打开链接)是姊妹篇,标签视图Tabbar在各大apps中实在是常见。不过对比起安卓,iOS的标签视图的设置与使用,似乎比较繁琐。而在《【iOS】表视图》(点击打开链接)我只完成了iOS中最简单的一种表视图,其实,在iOS,分组静态表的布局也很常见。下面举一个例子来说明iOS中标签视图Tab Bar View的使用与分组静态表使用。
如上图,我定义3个标签页,在第一个标签页中还使用了分组静态表布局去刻画登录页面。在登录页面输入完表单,则能跳转到第二个标签页中显示结果。第三个标签页则是简单地显示本程序的信息。具体制作步骤如下:
一、场景布局
1、在新建项目的时候,直接选择Tabbed Application,而不是往常的Single View Application可以得到一个成熟的标签视图模板的项目,我们在此之前进行修改即可。其实这两种新建方式没有区别,即使以Single View Application也可以自己在右下角拖出Tab bar Controller。
2、如图所示,将自带的First View Controller的视图和代码文件一并删除,用Table View Controller取代(也可以新建一个View Controller再拖个Table View进去)。并且新建一个View Controller,选中Tab Bar Controller按着Ctrl,将两者建立关联。
3、点选各个Tab Bar Item,修改其Title和Image,Title分别为“登录页面”、“输入结果”、“关于”,Image分别为“first”、"second"、"second"。
点选Tab Bar Controller,对于各个标签页选项双击之后,可以长按拖拽,从而控制各个标签页的顺序。
4、对于刚刚新建的Table View Controller“登录页面”中的Table View,修改其样式,Content改成Static Cells,Sections段数设置为3,然后Style设置为Grouped
旗下的3个Table View Section,第1个是有Header的,且Rows行数为2,其余2个行数为1。
在第一段中拖入两个Text Field,设置好字体Fonts为18号字和替换文本Placeholder,同时选择为无边框。
然后先在下面两个表格单元格拖入Label,改为“登录”和“关于”居中摆放,再打开这个单元格的Disclosure Indicator,不然居中的位置会有所偏移的。
同时设置这两个单元格的标签Tag分别为111和222,用于一会儿程序点击使用。
5、其余两个页面分别拖入Label摆到合适的位置,并调整好这个Label的大小和所容纳的行数。
至此,布局完毕,开始写代码。
二、代码编写
1、首先,和《【iOS】View跳转和传值》(点击打开链接)一样,为新建的Table View Controller新建Objective-C Class代码文件ViewController.h与ViewController.m。指明这个ViewController是继承于UITableViewController而不是UIViewController的!
同时在MainStoryboard.storyboard中指明,这个我们新建的Table View Controller“登录页面”的控制Class就是我们新建的这个ViewController文件。
2、然后和 《【iOS】点击按钮Button,更变标签文字Label的颜色》(点击打开链接)中一样,对“登录页面”中的两个TextField,“输入结果”页面中的Label进行组件的注册。并且由于我们涉及到跨页面的传值,所以在SecondViewController.h定义两个全局变量,并且在ViewController.h要引入SecondViewController.h这个头文件。所以ViewController.h如下所示:
//
// ViewController.h
// tab
//
// Created by pc on 17-7-19.
// Copyright (c) 2017年 pc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
@interface ViewController : UITableViewController
@property (weak, nonatomic) IBOutlet UITextField *textfield1;
@property (weak, nonatomic) IBOutlet UITextField *textfield2;
@end
SecondViewController.h如下所示:
//
// SecondViewController.h
// tab
//
// Created by pc on 17-7-19.
// Copyright (c) 2017年 pc. All rights reserved.
//
#import <UIKit/UIKit.h>
/*可以被其他变量操控的全局变量*/
NSString *username;
NSString *password;
@interface SecondViewController : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *label1;//承载输入结果的label1
@end
3、ViewController.m的代码如下所示,这里由于是一个Table View Controller视图,默认在这个视图是都被一个Table View填充了,所以无法用《【iOS】基本控件:文本输入框、开关、分段控件、滑块与输入键盘隐藏的问题》(
点击打开链接)和处理View视图一样,直接点击空白处来关闭键盘,只能通过用户开始拖拽界面的方式,来隐藏输入键盘了。
//
// ViewController.m
// tab
//
// Created by pc on 17-7-19.
// Copyright (c) 2017年 pc. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
//允许用户点击拖拽关闭键盘
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
[self.view endEditing:YES];
}
//允许用户通过点击return键关闭键盘
-(BOOL)textFieldShouldReturn:(UITextField *) textField{
[textField resignFirstResponder];
return YES;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath//单元格被点击之后所触发的函数
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];//拿到被点击单元格的指针
if(cell.tag==111){//如果点击的单元格的tag为111,也就是“登陆”
/*通知方式传递数值,用于每次切换标签页都能修改label1的值*/
NSDictionary *dictionary =[[NSDictionary alloc]initWithObjectsAndKeys:self.textfield1.text,@"textfield1",self.textfield2.text,@"textfield2", nil];//创建一个数据字典dictionary,里面存放我们要压入通知,传递给通知中心的变量
NSNotification *notification =[NSNotification notificationWithName:@"message_handler" object:nil userInfo:dictionary];//指明数据字典dictionary的送达地为通知中心message_handler
[[NSNotificationCenter defaultCenter] postNotification:notification];//发送通知
/*全局变量传递数值*/
username=self.textfield1.text;
password=self.textfield2.text;
[self.tabBarController setSelectedIndex:1];//从这个第0个标签页,切换到第1个标签页
}
else if(cell.tag==222){
[self.tabBarController setSelectedIndex:2];//切换到第2个标签页
}
}
@end
标签页切换其实就一行代码:self.tabBarController setSelectedIndex:X];表示切换到第X个标签页,大家可以看到无须传值,切换到第2个“关于”标签页是一个很简单的事情。
至于标签页传值的问题,我们看完SecondViewController.m的代码再说://
// SecondViewController.m
// tab
//
// Created by pc on 17-7-19.
// Copyright (c) 2017年 pc. All rights reserved.
//
#import "SecondViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
/*全局变量传递数值的方式*/
if(username&&password){
self.label1.text=[[NSString alloc]initWithFormat:@"传递过来的信息\n登陆名:%@,密码:%@",username,password];
}
/*通知传递数值的方式*/
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(message_handler:) name:@"message_handler" object:nil];//初始化通知中心,指明通知处理函数为message_handler
}
//通知的处理函数,也就是受到通知会做什么事情。
- (void)message_handler:(NSNotification *)notification{
self.label1.text=[[NSString alloc]initWithFormat:@"传递过来的信息\n登陆名:%@,密码:%@",notification.userInfo[@"textfield1"],notification.userInfo[@"textfield2"]];
}
@end
这里我似乎是多此一举,用两种方式来传递数值,其实不然,因为在这个“输入结果”的视图中,viewDidLoad这个初始化函数,只会在第一次切换到这个标签页之中触发一次,同时以后不再触发,而第一次进入这个页面的话,通知中心才刚刚被初始化,只有以后通过点击“登录页面”的“登录”按钮,才会每次发送一次信息,给消息处理函数message_handler进行处理。在现实中就分两种情况了,(1)用户直接点击“输入结果”页面,才输入信息登录(2)用户输入完信息登录,直接跳到这个标签页。所以要两种传值方式配合,来完成标签页的传值了。
最后说句题外话,这里的iOS消息传递,其实和《【Android】进度条与线程之间的消息处理》(点击打开链接)中利用消息处理的机制来更新组件,有异曲同工之妙。由于iOS标签页的特殊性,我们无法用《【iOS】View跳转和传值》(点击打开链接)中提到的设置属性的方式来传值了~只能做得这么复杂,我也不想的!