Toolbar使用gif图展示效果图:
NavigationBar使用gif效果图
导航栏和工具栏(UIToolbar and NavigationBar)
工具栏和导航栏实际上是有很大差距的,这里放到一起来学习是因为两者有个共同的特性,两者的item都是通过UIBarButtonItem实现的。
目录
UIToolbar
1.1 UIToolbar布局
1.2 UIBarButtonItem布局
1.3 Toolbar布局优化
1.4 Flexible Space让布局更美观
1.5 Fixed Space 固定空格
1.6 代码中体验UIToolbar中UIBarButtonItem的
2 使用代码布局UIToolbar和添加UIBarButtonItem
2.1 代码布局UIToolbar
2.2 weak属性引起的xcode警告
工具栏在IOS中是UIToolbar,在iphone应用中UIToolbar通常位于屏幕的底部,UIToolbar中按钮的数量一般最好不要添加多余5个,要不看起来会很紧凑,不太好看。
UIToolbar作为UIBarButtonItem的父容器,UIToolbar中的每一个按钮就是一个UIBarButtonItem。
这里通过Interface Builder 故事板拖拽布局,如下图:
往UIToolbar添加item元素UIBarButtonItem,同样通过拖拽加入,如下图:
在进过上面的步骤之后我们添加了6个UIBarButtonItem,然后我们得到下面的运行效果,如下图:
布局十分的不合理,很丑,而且并不是所说的最多显示5个按钮,这不是打脸嘛?不急,下面我们来优化,
这里我们将使用Flexible Space和Fixed Space,也就是可变空格和固定空格来优化布局,让item之间的举例变的合理,形如下图:
Flexible Space是一个弹性空格视图,在显示上是看不见的,但是它可以让item之间的间距都保持一致,并且随着item的数量变化而弹性变化,让布局Toolbar里面的item的布局变得更加的美观。
添加Flexible Space也同样可以通过拖拽的方式进行,如下操作图:
依次添加5个Flexibale Space后,得到下面效果图:
看起来效果似乎好很多,不过6个按钮看起来太挤了,网上说多余5个按钮的时候,只会显示5个,并且最后一个变成“更多”,这里测试发现并不是这样,实际上还可以添加7个,8个,只是这样不太美观。
总结:一下Flexible Space,它能够让item之间的控件弹性变化,但是能够保证item之间的间距都是一样的。
与Flexible Space相对应的是Fixed Space控件,如下图:
那么这个控件有什么特性了,相对于Flexible Space的伸缩性,它是固定不变的,这里就不做演示了,很简单。
给每一个item添加一个对应的点击事件,如下代码:
这里使用的是setAction给每一个item添加action,与button使用的addTarget不同,但是目的一样,当然也可以通过拖拽的方式直接连线,内部机制其实是一样的。
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIToolbar *mToolbar;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *itemFirst;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *itemSecond;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *itemThird;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *itemForth;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *itemFifth;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//给第一个按钮增加Target点击事件
[self.itemFirst setAction:@selector(onClickFirstItem:)];
[self.itemSecond setAction:@selector(onClickSecondItem:)];
[self.itemThird setAction:@selector(onClickThirdItem:)];
[self.itemForth setAction:@selector(onClickFourthItem:)];
[self.itemFifth setAction:@selector(onClickFifthItem:)];
}
- (IBAction)onClickFirstItem:(id)sender{
NSLog(@"first item isClicked");
}
- (IBAction)onClickSecondItem:(id)sender{
NSLog(@"second item isClicked");
}
- (IBAction)onClickThirdItem:(id)sender{
NSLog(@"Third item isClicked");
}
- (IBAction)onClickFourthItem:(id)sender{
NSLog(@"Fourth item isClicked");
}
- (IBAction)onClickFifthItem:(id)sender{
NSLog(@"Fifth item isClicked");
}
@end
上面代码运行的效果如下图:
上面是通过Interface Builder,通过拖拽控件的方式布局,下面我将使用纯代码的方式再做一次,
步骤:
1)申明变量属性mToolbar、itemFirst、itemSecond等
2)初始化mToolbar、itemFirst、itemSecond等
3)将itemFirst、itemSecond等UIBarButtonItem添加到UIToolbar,并使用Flexible Space优化布局
4)将mToolbar添加到跟布局中
源码如下:
@interface ViewController ()
//1、申明变量属性mToolbar、itemFirst、itemSecond等
@property (strong, nonatomic) IBOutlet UIToolbar *mToolbar;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *itemFirst;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *itemSecond;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *itemThird;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *itemForth;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *itemFifth;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//获取屏幕参数
CGRect screen = [[UIScreen mainScreen]bounds];
//获取屏幕的宽度
CGFloat screenWidth = screen.size.width;
//获取屏幕的高度
CGFloat screenHeight = screen.size.height;
//toolbar的默认高度系统给的是44,这里直接使用
CGFloat toolbarHeight = 44;
//2、初始化mToolbar、itemFirst、itemSecond等
//2.1 初始化toolbar,注意这里CGRectMake前两个参数是toolbar的坐标,也就是其左上角的坐标点,x比较好理解,y需要通过计算得到
self.mToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, screenHeight - toolbarHeight, screenWidth, toolbarHeight)];
//2.2 初始化itemFirst
self.itemFirst = [[UIBarButtonItem alloc] initWithTitle:@"首页" style:UIBarButtonItemStylePlain target:self action:@selector(onClickFirstItem:)];
//2.3 初始化itemFirst
self.itemSecond = [[UIBarButtonItem alloc] initWithTitle:@"风景" style:UIBarButtonItemStylePlain target:self action:@selector(onClickSecondItem:)];
//2.4 初始化itemFirst
self.itemThird = [[UIBarButtonItem alloc] initWithTitle:@"帅哥" style:UIBarButtonItemStylePlain target:self action:@selector(onClickThirdItem:)];
//2.5 初始化itemFirst
self.itemForth = [[UIBarButtonItem alloc] initWithTitle:@"靓妹" style:UIBarButtonItemStylePlain target:self action:@selector(onClickFourthItem:)];
//2.6 初始化itemFirst
self.itemFifth = [[UIBarButtonItem alloc] initWithTitle:@"我的" style:UIBarButtonItemStylePlain target:self action:@selector(onClickFifthItem:)];
//2.7 Flexibale Spacekec初始化要注意了,并没有我们想的FlexibaleSpacekec这个控件,而是UIBarButtonItem的一种
UIBarButtonItem *flexibaleSpaceItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
//3、将itemFirst、itemSecond等UIBarButtonItem添加到UIToolbar,并使用Flexible Space优化布局
self.mToolbar.items = @[self.itemFirst,flexibaleSpaceItem,
self.itemSecond,flexibaleSpaceItem,
self.itemThird,flexibaleSpaceItem,
self.itemForth,flexibaleSpaceItem,
self.itemFifth];
//4、将mToolbar添加到跟布局中
[self.view addSubview:self.mToolbar];
}
- (IBAction)onClickFirstItem:(id)sender{
NSLog(@"first item isClicked");
}
- (IBAction)onClickSecondItem:(id)sender{
NSLog(@"second item isClicked");
}
- (IBAction)onClickThirdItem:(id)sender{
NSLog(@"Third item isClicked");
}
- (IBAction)onClickFourthItem:(id)sender{
NSLog(@"Fourth item isClicked");
}
- (IBAction)onClickFifthItem:(id)sender{
NSLog(@"Fifth item isClicked");
}
@end
测试结果一上一致:
注意以上代码,属性变量的声明和通过Interface Builder拖拽生成的不一样:
拖拽生成的是:@property (weak, nonatomic) IBOutlet UIBarButtonItem *itemFifth;
代码写出来是:@property (strong, nonatomic) IBOutlet UIBarButtonItem *itemFifth;
如果我们继续使用@property (weak, nonatomic) IBOutlet UIBarButtonItem *itemFifth;也就是使用weak属性修饰
itemFifth变量在使用的时候Xcode会给警告,原因是OC引入了自动ARC机制,自动管理内存,以前是需要手动管理的。
这里涉及到对oc或者是c语言中的weak指针和strong指针的知识点,这里推荐看一篇博客: ARC指南1 - strong和weak指针,同时对OC或者C语言不太熟悉的可以看他的系列:M了个J
解决警告的方法就是吧weak指针换成strong指针类型。
相信做过android开发或者0基础的同学也都用过微信,底部的tab切换都知晓。对于具有Android开发背景的同学更是深刻的知道,在一个Activity的界面中通过Tab+Fragment来实现page的切换,与Toolbar类似。
而NavigationBar这里要做的工作类似于Activity 到 Activity之间的切换。
Interface Builder 拖拽方式布局:
1) Main.storyboard头部添加NavigationBar
2)往NavigationBar添加Bar Button Item,左右各一个
操作如下:
3)然后将NavigationBar的title和BarItem的Title修改一下,如下图:
4)给左右按钮添加点击事件,命名为back
对应的代码如下:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)back:(id)sender {
NSLog(@"back click");
}
@end
测试结果:
上一节使用了Interface Builder拖拽的方式在故事板上布局,这一节使用纯代码构建。
步骤如下:
1)初始化NavigationBar,举例头部状态栏20,避免遮住状态栏
2)给NavigationBar添加左右两个item
3)将NavigationBar添加到跟布局中
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CGRect screen = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screen.size.width;
CGFloat navBarHeight = 44;//系统默认的NavigationBar的高度
//1)初始化NavigationBar,举例头部状态栏20,避免遮住状态栏
UINavigationBar *navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 20, screenWidth, navBarHeight)];
//2)给NavigationBar添加左右两个item
UIBarButtonItem *itemBack = [[UIBarButtonItem alloc] initWithTitle:@"back" style:UIBarButtonItemStylePlain target:self action:@selector(back:)];
UIBarButtonItem *itemNext = [[UIBarButtonItem alloc] initWithTitle:@"next" style:UIBarButtonItemStylePlain target:self action:@selector(next:)];
UINavigationItem *nagationItem = [[UINavigationItem alloc]initWithTitle:@"首页"];
nagationItem.leftBarButtonItem = itemBack;
nagationItem.rightBarButtonItem = itemNext;
navigationBar.items = @[nagationItem];
//3)将NavigationBar添加到跟布局中
[self.view addSubview:navigationBar];
}
- (IBAction)back:(id)sender {
NSLog(@"back click");
}
- (IBAction)next:(id)sender {
NSLog(@"back next");
}
@end
注意这里添加item的方式与Toolbar又有所不同。
由于目前的知识点还没有达到对于页面的管理,真正的进行ViewController之间的跳转,这里只是写到回调,之后会有相关笔记。