在以前几个项目中都是多人开发,为避免在StoryBoard中代码修改很可能出现的问题,开发中几乎不用StoryBoard。这两天没啥事儿就想着系统的捣鼓一下StoryBoard,看看它究竟是个什么鬼,在实际的开发中会出现什么样的问题。小弟职场菜鸟一枚,大神们嘴下留情,望不吝赐教,不胜感激!
一、在StoryBoard中导航栏可以通过拖控件的方式添加Bar Button Item,在导航控制器或者控制器中更改Item的样式,标题的字体的颜色大小等属性,当然在StoryBoard中一步到位更改标题和Item属性也未尝不可。如下图所示。
我们知道,用系统的导航栏,导航栏背景色有微透明色,在小弟所经历的开发中,这些设计、UI们老师给我们找事情做,什么我不要它透明的、我想让字体是这样的、左边的返回按钮能不能我自定义个图片诸如此类,说实话我觉得根本没那个必要跟他们讲道理,因为设计人家才是专业的,为此争执的时间也把他们的需求给做好了(我是不是太随和了)。其实,要想实现他们的需求可以有两种方式:
1.使用系统的导航栏。
(1)改变背景色
UIImage *backgroundImage = [self imageWithColor:[UIColor whiteColor]];[self.navigationController.navigationBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.translucent = NO;
[self.navigationController.navigationBar setTitleTextAttributes:
@{NSFontAttributeName:[UIFont systemFontOfSize:17],
NSForegroundColorAttributeName:[UIColor colorWithRed:1.0 green:75/255.0 blue:90/255.0 alpha:1]}];
//创建纯色背景的方法
-(UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
(2)自定义Bar Button Item (有时候需要增加点击的范围,可以将Button设置的大一点,便于交互)。在自定义Bar Button Item的时候我选择新建一个继承与UIBarButtonItem的类别。
+ (instancetype)itemWithNorImage:(NSString *)image highImage:(NSString *)highImage target:(id)target action:(SEL)action
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
btn.frame = CGRectMake(0, 0, 74, 44);
[btn setImage:[UIImage imageNamed:highImage] forState:UIControlStateHighlighted];
[btn sizeToFit];
[btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
UIView *containVew = [[UIView alloc] initWithFrame:btn.bounds];
[containVew addSubview:btn];
return [[UIBarButtonItem alloc]initWithCustomView:containVew];
}
然后在控制器中调用方法:self.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithNorImage:@"left" highImage:@"" target:self action:@selector(back:)];
2.自定义导航栏。
自定义导航栏可以纯代码创建View,在View上设置约束,自定义title和返回按钮,如果项目中有特殊需要可以在这个View上创建需要的各个类型的控件,并写成公开方法以供调用或进行隐藏显示等操作。 当然也可以创建一个View的xib文件,在custom class中填写集成与UIView的一个子类view的类名。
在进行创建的StoryBoard的层级图中我们不难发现,大多数的项目中都可以通过创建几个BaseViewController的方式进行层级的继承,根据开发的不同需要继承不同的父类在显示导航栏属性上面做一些可靠的调节,满足日常开发需要。
二、TabBar在demo中将根视图控制器的custom Class 写成TabbarController类名,在代码中定义TabBar的样式,在View中自定义Button,通过代理方法传递点击的是哪个导航控制器。
在TabBarView自定义完成,项目能正常跑动,但是在点击自定义的TabBar的时候会出现以下问题。
知道问题的所在,定位到出现此类问题的原因:
为了能同时出现自定义NavigationBar和经过更改系统的NavBar显示不透明的要求,最后一个导航控制器是系统的导航控制器,其他四个导航控制器的头部均为自定义。
问题出在了我在控制器中设置了self.navigationController.title = @"嘻嘻哈哈";这个设置也牵连到TabBarButton的设置,也就是说系统同时设置了两个地方 ,一个是NavigationController的title另一个就是对应的TabBarButton,也就是说将按钮重新赋值了,掩盖了自定义的tabBarView。
好吧,既然这样不行,那就换个方法,设置self.title,其实是一样的的效果,因为self.title设置的就是导航控制器的title,FifthTableVC是导航控制器的根控制器。
难道没有解决问题的方法了吗?答案是否定的,导航控制器和TabBar控制器是两个单独的控制器,导航的标题肯定有对应的设置方法,没错就是self.navigationItem.title这个属性,这个属性只改变导航控制器的导航条上面的控件属性。问题也就迎刃而解。如有不妥的地方,欢迎指正。
demo源码,git下载地址:StoryBoardTest-demo