1、UINavigationController使用流程

UINavigationController为导航控制器,在iOS里经常用到。

我们看看它的如何使用:

下面的图显示了导航控制器的流程。最左侧是根视图,当用户点击其中的General项时 ,General视图会滑入屏幕;当用户继续点击Auto-Lock项时,Auto-Lock视图将滑入屏幕。相应地,在对象管理上,导航控制器使用了导航堆栈。根视图控制器在堆栈最底层,接下来入栈的是General视图控制器和Auto-Lock视图控制器。可以调用pushViewControllerAnimated:方法将视图控制器推入栈顶,也可以调用popViewControllerAnimated:方法将视图控制器弹出堆栈。

上图来自苹果官网。

2、UINavigationController的结构组成

看下图,UINavigationController有Navigation bar  ,Navigation View ,Navigation toobar等组成。

3、新建一个项目,现在我们建立一个例子,看看如何使用UINavigationController

a.命名为NavigationControllerDemo,为了更好理解UINavigationController,我们选择Empty Application模板

b、创建一个View Controller,命名为RootViewController,默认勾上With XIB for user interface.

c.选择正确位置创建完成,这时项目里多了三个文件,分别是RootViewController.h RootViewController.m RootViewController.xib文件。

d、将RootViewControoler添加到window上,在AppDelegate.m 文件的didFinishLaunchingWithOptions方法中创建添加navController,RootViewController视图。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

// Override point for customization after application launch.

RoowViewController *rootViewController = [[RoowViewController alloc] init];

rootViewController.title = @"rootView";

UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:rootViewController];

self.window.rootViewController = nav;

rootViewController = nil;

nav  = nil;

self.window.backgroundColor = [UIColor whiteColor];

[self.window makeKeyAndVisible];

return YES;

}

e、 在RootViewControoler中添其它视图,这里添加了一个tableView.

- (void)viewDidLoad

{

[super viewDidLoad];

self.myArray = @[@“navigationItem”,@“Toolbar"];

UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds];

tableView.backgroundColor = [UIColor clearColor];

tableView.delegate = self;

tableView.dataSource = self;

[self.view addSubview:tableView];

tableView = nil;

}

#pragma mark - UITableViewDelegate And UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

return self.myArray.count;

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

static NSString *cellString_=@"tableCell";

UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellString_];

if (cell==nil) {

cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellString_];

cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;

}

cell.textLabel.text=self.myArray[indexPath.row];

return cell;

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

if (indexPath.row == 0) {

OneViewController *oneViewController = [[OneViewController alloc] init];

[self.navigationController pushViewController:oneViewController animated:YES];

oneViewController = nil;

}

}

f.现在Root视图添加完成,看看运行效果.

现在点击第一行就可以将视图推到下一个视图显示了,

控制视图推进推出的主要方法如下:

pushViewController:viewController animated:BOOL

(加载视图控制器)

– 添加指定的视图控制器并予以显示

popViewControllerAnimated:BOOL

(推出当前视图控制器)

– 弹出并向左显示前一个视图

popToViewController:viewController animated:BOOL

(推到指定视图控制器)

– 回到指定视图控制器, 也就是不只弹出一个

popToRootViewControllerAnimated:BOOL

退到根视图控制器

setNavigationBarHidden:BOOL animated:BOOL

设置导航栏是否显示

关于pushViewController:animated:的动画效果一般情况我们使用默认的动画就行,但我们也可以自定动画内容,我们可以使用CATransition来实现转换动画效果,代码如下:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

if (indexPath.row == 0) {

OneViewController *oneViewController = [[OneViewController alloc] init];

CATransition *animation = [CATransition animation];

[animation setDuration:0.5];

[animation setType: kCATransitionMoveIn];

[animation setSubtype: kCATransitionFromTop];

[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];

[self.navigationController pushViewController:oneViewController animated:NO];

oneViewController = nil;

[self.navigationController.view.layer addAnimation:animation forKey:nil];

}

}

4、navigationItem

  我们都知道navigationItem是UIViewController的一个属性,这个属性是为UINavigationController服务的。文档中是这么解释的“The navigation item used to represent the view controller in a parent’s navigation bar. (read-only)”,即navigation item在navigation Bar代表一个viewController,具体一点儿来说就是每一个加到navigationController的viewController都会有一个对应的navigationItem,该对象由viewController以懒加载的方式创建,稍后我们可以在对象中堆navigationItem进行配置,可以设置leftBarButtonItem, rightBarButtonItem, backBarButtonItem, title以及prompt等属性。前三个每一个都是一个UIBarButtonItem对象,最后两个属性是一个NSString类型描述,注意添加该描述以后NavigationBar的高度会增加30,总的高度会变成74(不管当前方向是Portrait还是Landscape,此模式下navgationbar都使用高度44加上prompt30的方式进行显示)。当然如果觉得只是设置文字的title不够爽,你还可以通过titleview属性指定一个定制的titleview,这样你就可以随心所欲了,当然注意指定的titleview的frame大小,不要显示出界。

a、添加UIBarButtonItem,

初始化UIBarButtonItem的方法有以下几种方法:

- (id)initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action;

- (id)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action;

- (id)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(id)target action:(SEL)action;

- (id)initWithCustomView:(UIView *)customView; //这个方法可以用来自定UIBarButtonItem

这里重点介绍下

- (id)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(id)target action:(SEL)action;

UIBarButtonSystemItem的风格,这是系统自带的按钮风格,看下图,你不用一个个试验,你也知道想用那个item,如下图:

给navigationItem 添加 UIBarButtonItem的方法有:

@property(nonatomic,retain) UIBarButtonItem *leftBarButtonItem;

@property(nonatomic,retain) UIBarButtonItem *rightBarButtonItem;

- (void)setLeftBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;

- (void)setRightBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;

@property(nonatomic,copy) NSArray *leftBarButtonItems NS_AVAILABLE_IOS(5_0);

@property(nonatomic,copy) NSArray *rightBarButtonItems NS_AVAILABLE_IOS(5_0);

- (void)setLeftBarButtonItems:(NSArray *)items animated:(BOOL)animated NS_AVAILABLE_IOS(5_0);

- (void)setRightBarButtonItems:(NSArray *)items animated:(BOOL)animated NS_AVAILABLE_IOS(5_0);

下面举例说明:

- (void)viewDidLoad

{

[super viewDidLoad];

self.view.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];

UIBarButtonItem *buttonItem1 = [[UIBarButtonItem alloc] initWithTitle:@"登录"

style:UIBarButtonItemStyleBordered

target:self

action:@selector(barButtonItemClick:)];

UIBarButtonItem *buttonItem2 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"setUp.png"]

style:UIBarButtonItemStyleBordered

target:self

action:@selector(barButtonItemClick:)];

UIBarButtonItem *buttonItem3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd

target:self

action:@selector(barButtonItemClick:)];

UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 7, 50, 30)];

button.backgroundColor = [UIColor blueColor];

[button setTitle:@"按扭" forState:UIControlStateNormal];

UIBarButtonItem *buttonItem4 = [[UIBarButtonItem alloc] initWithCustomView:button];

self.navigationItem.leftBarButtonItem = buttonItem1;

self.navigationItem.rightBarButtonItems = @[buttonItem2, buttonItem3, buttonItem4];

}

//UIBarButtonItem击事件

- (void)barButtonItemClick:(UIBarButtonItem *)barButton{

//添加你要响应的代码

}

运行效果.

b、自定义backBarButtonItem

在项目中使用UINavigationController导航,当第一级页面的title较长,在进入第二级页面后返回按钮backBarButtonItem的title就会变得很长,于是使用代码对leftButtonItem的title文本进行修改,无论是设置self.navigationItem.leftBarButtonItem.title = @"返回";还是self.navigationItem.backBarButtonItem.title = @"返回";都没有效果,title始终不会发生变化,要怎第才能修改返回按扭的title呢?

原来使用pushViewController切换到下一个视图时,navigationController按照以下3条顺序更改导航栏的左侧按钮。

1)、如果B视图有一个自定义的左侧按钮(leftBarButtonItem),则会显示这个自定义按钮;

2)、如果B没有自定义按钮,但是A视图的backBarButtonItem属性有自定义项,则显示这个自定义项;

3)、如果前2条都没有,则默认显示一个后退按钮,后退按钮的标题是A视图的标题。

按照这个解释,我把UIBarButtonItem *backItem……这段代码放在A视图的pushViewController语句之前。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

if (indexPath.row == 0) {

ItemOneViewController *itemOne = [[ItemOneViewController alloc] init];

itemOne.title = @"addItem";

[self.navigationController pushViewController:itemOne animated:YES];

itemOne = nil;

}

else{

ItemTwoViewController *itemTwo = [[ItemTwoViewController alloc] init];

itemTwo.title = @"setBackItemTItle";

UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithTitle:@"返回"

style:UIBarButtonItemStyleBordered

target:nil

action:nil];

self.navigationItem.backBarButtonItem = back;

back = nil;

[self.navigationController pushViewController:itemTwo animated:YES];

itemTwo = nil;

}

}

OK问题解决了,B视图的后退按钮的标题变成“返回“了,也可以使用自定义的返回按扭。

c、自定义titleView,

UINavigationController的title可以用别的view替代,比如用UIview、 UIButton、 segmentedController、UILable等,在下面的代码我用UIButton来演示.代码如下

- (void)viewDidLoad

{

[super viewDidLoad];

UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 90, 35)];

button.backgroundColor = [UIColor blueColor];

[button setTitle:@"自定义titleView" forState:UIControlStateNormal];

self.navigationItem.titleView = button;

}

注意:view的大小不要大小导航栏的大小,要不在就会显示不下。

运行效果如图:

5、Toolbar 

在前面我们讲了UINavigationController有Navigation bar  ,Navigation View ,Navigation toolbar等组成,下面就讲解一下toolbar的使用,

toolbar在UINavigationController默认是隐藏的,可通过下面的代码显示出来。

self.navigationController.toolbarHidden = NO;

[self.navigationController setToolbarHidden:NO animated:YES];

在ToolBar上添加UIBarButtonItem,新建几个UIBarButtonItem,然后以数组的形式添加到Toolbar中

{

[super viewDidLoad];

self.navigationController.toolbarHidden = NO;

UIBarButtonItem*one=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd

target:nil

action:nil];

UIBarButtonItem*two=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks

target:nil

action:nil];

UIBarButtonItem*three=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAction

target:nil

action:nil];

UIBarButtonItem*four=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemEdit

target:nil

action:nil];

UIBarButtonItem*flexItem=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace

target:nil

action:nil];

[self setToolbarItems:@[flexItem,one,flexItem,two,flexItem,three,flexItem,four,flexItem]];

}

注意:用[self.navigationController.toolbar setItems:(NSArray *) animated:(BOOL)]这个方法添加item是不起效果的。

运行效果:

但调用这个方法后所有UINavigationController中的viewController都会显示出toolbar.如下图:

所以为了不出现这种情况可以不用UINavigationController中的toolbar、需重写toolbar来实现。这样在返回上级视图时就不会出现本来隐藏着的toolbar,代码如下:

- (void)viewDidLoad

{

[super viewDidLoad];

UIBarButtonItem*one=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd

target:nil

action:nil];

UIBarButtonItem*two=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks

target:nil

action:nil];

UIBarButtonItem*three=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAction

target:nil

action:nil];

UIBarButtonItem*four=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemEdit

target:nil

action:nil];

UIBarButtonItem*flexItem=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace

target:nil

action:nil];

UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 44,self.view.frame.size.width, 44)];

[toolBar setBarStyle:UIBarStyleBlack];

toolBar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;

[toolBar setItems:@[flexItem,one,flexItem,two,flexItem,three,flexItem,four,flexItem] animated:YES];

[self.view addSubview:toolBar];

}

运行效果图

6、设置导航栏的一些属性

设置导航栏中title的字体效果

NSDictionary *dict = @{UITextAttributeTextColor: [UIColor colorWithRed:27.0/255 green:125.0/255 blue:197.0/255alpha:1],

UITextAttributeTextShadowColor: [UIColor whiteColor]};

self.navigationController.navigationBar.titleTextAttributes = dict;

运行效果图:

设置导航栏的背影色

self.navigationController.navigationBar.tintColor = [UIColor redColor];

上面方法只能用在ios7以下有效,在ios7以下设置的是导航中按扭字体的颜色,所以在ios7中修改导航栏的背影色要用

self.navigationController.navigationBar.barTintColor = [UIColor blueColor];

可能过系统的版本来进行相应的设置,如果不加判断而直接写上两个属性的话低版本的统中就会闪退,因为7.0以下的纺统没有barTintColor这个属性值

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {

// iOS 7 code

self.navigationController.navigationBar.barTintColor = [UIColor brownColor];

}

else {

// iOS 6.x code

self.navigationController.navigationBar.tintColor = [UIColor brownColor];

}

动行效果图:

用图片设置导航栏的背影

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav_bg.png"]forBarMetrics:UIBarMetricsDefault];

动行效果图:

将导航栏设置为半透明,

self.navigationController.navigationBar.translucent = YES; //设置这个属性后视图的坐标会上移到导航栏的上面,

将导航栏设置为透明的效果

先做一张全透明的图片1*1的像素就行,作为UINavigationBar的背景色,然后将barStyle设置成通道就可以了。

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"clear.png"]forBarMetrics:UIBarMetricsDefault];

self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;

动行效果图:

方法有很多,个人觉得这个最简单,可以现实各种效果。

总结下上面讲到的属性使用方法

//设置导航栏的背影色,ios6和ios7要区别对待,设置为透明色(clearColor)时无效,为黑色背影

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {

// iOS 7 code

self.navigationController.navigationBar.barTintColor = [UIColor clearColor];

}

else {

// iOS 6.x code

self.navigationController.navigationBar.tintColor = [UIColor clearColor];

}

//设置导航栏title字体的样式

NSDictionary *dict = @{UITextAttributeTextColor: [UIColor colorWithRed:27.0/255 green:125.0/255blue:197.0/255 alpha:1],

UITextAttributeTextShadowColor: [UIColor whiteColor]};

self.navigationController.navigationBar.titleTextAttributes = dict;

//设置导航栏的背影图片,可以设置成透明效果。

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav_bg.png"]forBarMetrics:UIBarMetricsDefault];

//设置导航栏的样式

self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;

//门置导航栏为半透明效果,同时视图坐标上移。

self.navigationController.navigationBar.translucent = YES;

注意,上面设置和修改的属性都是全局的,设置后在当前这个UINavigationController中的导航栏都将改变。

如果想在局部的视图中修改导航的属性设置怎么办呢,可通过实现UINavigationControllerDelegate来实现。

例如:

@interface PicturePreviewViewController : UIViewController<<span style="color: #ff2500">UINavigationControllerDelegate>

将代理方法指向当前的类

self.navigationController.delegate = self;

在实现类中加入这个代理的方法及具体操作如下:

- (void) navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

// 如果进入的是当前视图控制器

if (viewController == self) {

//可在这里设置当前视图导航栏的效果

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav_bg.png"]forBarMetrics:UIBarMetricsDefault];

// 背景设置为黑色

self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0.000 green:0.000blue:0.000 alpha:1.000];

// 设置为半透明

self.navigationController.navigationBar.translucent = YES;

}

else {

//进入其他视图控制器,需要恢复之前的设置效果

[self.navigationController.navigationBar setBackgroundImage:nilforBarMetrics:UIBarMetricsDefault];

// 背景颜色设置为系统默认颜色

self.navigationController.navigationBar.tintColor = nil;

// 设置为半透明为NO

self.navigationController.navigationBar.translucent = NO;

}

}

好了,关于UINavigationController的使用就讲到这里,通过上面的介绍可以设置出各种效果的导航栏来满足视图布局的需求。

UINavigationController的使用的更多相关文章

  1. iOS UINavigationController(内容根据iOS编程编写)

    我们知道 UITabBarController 对象,可以通过使用该对象,用户可以切换不同的屏幕.当要切换的各个屏幕之间没有相互依存关系的时候,该对象可以很好的完成任务.但是当多个屏幕互有关系的时候, ...

  2. UINavigationController

    知识点: 1)UINavigationController 2)UINavigationBar 3)UINavigationItem 4)UIToolBar ===================== ...

  3. 混合使用UITabBarController和UINavigationController

    混合使用这两个控件的好处是我们可以在NavigationBar添加更多的东西,如标题,按钮等.让用户能够获得更多的信息. UITabBarController的属性ViewControllers接受以 ...

  4. 基本组件的使用——UINavigationController

    作用:在多个ViewController中切换.UINavigationController内部以栈的形式维护一组ViewController, 因此,当导航进入一个新视图的时候,会以push的形式将 ...

  5. 解决UINavigationController在pushViewController时出现的"卡顿"问题

    进行开发中,遇到了个小问题: 在使用UINavigationController的-pushViewController:animated:执行入栈一个子控制器操作时(即最新栈顶子控制器),会出现推出 ...

  6. UINavigationController导航控制器初始化 导航控制器栈的push和pop跳转理解

    (1)导航控制器初始化的时候一般都有一个根视图控制器,导航控制器相当于一个栈,里面装的是视图控制器,最先进去的在最下面,最后进去的在最上面.在最上面的那个视图控制器的视图就是这个导航控制器对外展示的界 ...

  7. IOS 学习 开发 自定义 UINavigationController 导航

    文件目录如下:基本导航顺序: root -> First -> Second -> Third.其中,FirstViewController作为 navigation堆栈的rootv ...

  8. APP标配控制器:UINavigationController

    导航控制器UINavigationController简介: 只要看到控制器界面上部有一个条就是导航控制器UINavigationController 导航控制器最上面有一个条是导航条高度44,Y值是 ...

  9. UIScrollerView遇到UINavigationController

    今天在UITabBarController  的第一个Tab 页面中放入一个ScrollView, 原本以为可以正常运行. 结果却让人大跌眼镜.  每当我手动滚动或者 缓慢导航到另外一个页面时,当前的 ...

  10. IOS开发之控件篇UINavigationController第一章 - 介绍

    UINavigationController是一个比较常见的控件,它连接个视图,例如一个视图走到另外一个视图,之间的联系都可以用这个NavigationController的方法 一般都会由两个部分组 ...

随机推荐

  1. 【面试题042】翻转单词顺序VS左旋转字符串

    [面试题042]翻转单词顺序VS左旋转字符串 题目一:     输入一个英文句子,反转句子中单词的顺序,但单词内字符的顺序不变.为简单起见,标点符号和普通字母一样处理.     例如输入字符串“I a ...

  2. uva 10564

    Problem FPaths through the HourglassInput: Standard Input Output: Standard Output Time Limit: 2 Seco ...

  3. POJ 1185 炮兵阵地 (状压DP)

    题目链接 题意 : 中文题不详述. 思路 :状压DP,1表示该位置放炮弹,0表示不放.dp[i][j][k],代表第 i 行的状态为k时第i-1行的状态为 j 时放置的最大炮弹数.只是注意判断的时候不 ...

  4. android真机自动化测试

    appium执行用例时报错问题: 问题解析: 一般该种情况都是因为来连接了多个设备,验证办法:cmd->执行adb devices  看结果是否是多个devices ,如果是这个问题,停掉多余设 ...

  5. NPOI之Excel——合并单元格、设置样式、输入公式

    首先建立一个空白的工作簿用作测试,并在其中建立空白工作表,在表中建立空白行,在行中建立单元格,并填入内容: //建立空白工作簿 IWorkbook workbook = new HSSFWorkboo ...

  6. Gradle Goodness: Using and Working with Gradle Version

    To get the current Gradle version we can use the gradleVersion property of the Gradle object. This r ...

  7. Spring中RedirectAttributes对象重定向传参

    Spring3中的FlashAttribute 为 了防止用户刷新重复提交,save操作之后一般会redirect到另一个页面,同时带点操作成功的提示信息.因为是Redirect,Request里 的 ...

  8. 2016网易实习生编程题:n个骰子的和等于m

    题目 骰子的点数是1 到 6,当有n个骰子的时候,其点数和等于m的数量 如当n = 4 m = 23时候 有下面四种: 5666656666566665 解题 深度优先,开始第一感觉很复杂,然后就没有 ...

  9. 在telnet下操作memcache详解(操作命令详解)

    这篇文章主要介绍了在telnet下操作memcache详解,telnet下的memcache操作命令详解,需要的朋友可以参考下 在定位问题.测试等时候经常需要对memcache的数据进行一些操作,但是 ...

  10. vmware通过vmnet8共享本地网络

    转载于:http://zhaolongchn.blog.163.com/blog/static/19065850420122595117886/ 1,首先将真实电脑的虚拟网卡VMnet8启用 2,然后 ...