一、屏幕原点坐标的研究
小伙伴们可能发现,我们给一个空间设置origin为(0,0)的时候,有时候这个点会再屏幕的最左上角(有导航栏的情况下还可能会被导航栏给盖住),有时候又在导航栏的下边,都是同样的原点坐标,那么为什么会出现这种情况呢?下面给出答案:
一个controller的view的原点位置受self.navigationController. navigationBar 的 setTranslucent (BOOL) 属性控制,在 iOS7 以后 translucent 属性默认为 YES。
translucent 为YES:原点位置坐标为屏幕左顶端,即屏幕坐标系(0 , 0),含义为毛玻璃、半透明效果。
translucent 为NO:原点位置坐标为导航栏的下边的左顶端,即屏幕坐标系(0 , 64),此时导航栏不透明。
注意,当我们设置navigationBar的背景图片setBackgroundImage(注意是背景图片不是背景颜色)的时候,坐标起点也会变成(0,64),因为当我们设置背景图片的时候,系统会自动修改translucent为NO。
二、自定制导航栏
修改导航栏可以采用全局修改(一般在appDelegate中或者在父navigationController中设置navigationBar ),也可以单独在相应的页面设置。
全局appearance修改:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
//后续对bar设置,代码省略。
父navigationController修改:
获取self.navigationBar设置,代码省略。
单独页面设置:
self.navigationController.navigationBar设置,代码省略。
注:下文我们的示例代码都是全局设置。
1.修改导航栏的“背景”颜色
修改导航栏颜色有如下几种方式:
1.1 通过backgroundColor进行设置:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
navigationBarApperance.backgroundColor = [UIColor redColor];
navigationBarApperance.translucent = YES;
此方式需要translucent=YES为前提,而且设置出来的背景颜色不纯,会被导航栏的毛玻璃效果遮挡(至于为什么会被遮挡下文会讲),此方式基本不成功,效果太傻缺,而且效果产生的优先级会很低,如果后面再设置navigationBar的barTintColor,会覆盖掉这个效果。
综上,次方式直接废弃。
1.2 通过barTintColor进行设置:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
navigationBarApperance.barTintColor = [UIColor redColor];
如上图可以看到底部会有一条浅黄色(这个浅黄色是系统根据你导航栏的颜色自动适配的一个颜色)的分割线阴影,这条分割阴影是用来分割导航栏和下面视图的。如你不想要分割线,你也可以通过设置相同颜色的阴影图片去解除:
navigationBarApperance.shadowImage = [UIImage imageWithColor:[UIColor redColor]];
此方式设置的背景色,可以达到效果,但是效果产生的优先级比较弱没有下面1.3的设置背景图片高,同学们可以根据实际情况考量是否选择此方法。
综上,此方法可行,优先级相对弱,推荐,综合考量使用。
1.3 通过设置setBackgroundImage进行设置:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
[navigationBarApperance setBackgroundImage:[UIImage imageWithColor:[UIColor redColor]] forBarMetrics:UIBarMetricsDefault];
此方法设置的导航栏底部也会有一条浅黄的分割线阴影,和上面barTintColor效果一样,底下的分割线阴影也可以自动以设置。但是需要注意的是,此方法设置的优先级是最高的,会覆盖掉1.1,1.2中所有设置的背景色。
验证如下:
UINavigationBar * navigationBarApperance = [UINavigationBar appearance];
[navigationBarApperance setBackgroundImage:[UIImage imageWithColor:[UIColor whiteColor]] forBarMetrics:UIBarMetricsDefault];
navigationBarApperance.barTintColor = [UIColor redColor];
以上代码我先设置白色背景图,再设置红色barTintColor,但是红色的背景色没有生效,还是被白色背景图覆盖,如下图:
综上,此方法可行,优先级最高,推荐,综合考量使用。
这里说个查bug的小提示,当我们在某个页面设置了导航栏背景色,但是没有生效,这个时候我们需要检查下是不是我们用的bartintColor设置的被父类的设置背景图给覆盖了,导致没有生效,这个时候你就需要也用设置背景色来设置了。
下面我们针对前面提出的为什么设置的backgrandColor会被遮挡做出解释。
导航栏的层级图如下:
从上图我们可以看到,导航栏一共分为4大层,分别是,
1:背景色(backgroundColor)层,在最下面
2:背景层(barbackground),用作父视图
3:背景图片(imageview)层,此处有2个imageview,一个是背景图片,一个市分割线图片
4:主内容(contentview)层,用来显示navigationItem,比如导航栏的title,titleview,barButtonItem等。
通过层级我们可以看到,我们前面之所以设置的背景色显示不出来,是因为这个背景色在最底层,会被上面的背景层给遮挡,个人感觉说白了,我们设置导航栏的背景色就是无用的。
2.设置导航栏上的字体颜色
2.1 设置导航栏左右两边barbuttonItem的颜色:tintColor
navigationBarApperance.barTintColor = [UIColor greenColor];
注意:这种方式不能改变导航栏中间标题的颜色
barbuttonItem的颜色也可以通过自定制视图设置:
UIButton *leftBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[leftBtn setTitle:@"左边" forState:UIControlStateNormal];
[leftBtn setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:leftBtn];
以上这种自定制设置如果设置了颜色会覆盖掉前面设置的tintColor。
2.2 设置导航栏中间标题的颜色,字体:通过设置属性字符串实现TitleTextAttributes
navigationBarApperance.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor redColor],NSFontAttributeName:[UIFont systemFontOfSize:18]};
这里说下,设置页面导航栏标题的方式,有两种:
方式一:self.title = @"首页";
方式二:self.navigationItem.title = @"首页";
这两种方式都可以设置标题,而且效果是一样的,如果这两个方式都设置了标题,那么最后的标题会覆盖掉前面的设置的。
3.梳理下navigationBar,navigationItem的关系
navigationBar是UINavigationController的一个属性,主要用来设置导航栏颜色(背景色和镂空色tintColor)
navigationItem是UIViewController的一个分类UINavigationControllerItem中的属性,主要用来自定制导航栏上显示的东西,包括左右两边的barbuttonItem,中间的title或者中间的titleview。navigationItem主要是前面介绍的导航栏层级中最上层contentview的子视图。
三、常用设置导航栏,tabbar代码
1.统一设置NavigationBar的颜色、tint颜色、、字体
// 设置导航栏的颜色 [[UINavigationBar appearance] setBarTintColor:[UIColor redColor]]; // 设置tint颜色 [[UINavigationBar appearance] setTintColor: [UIColor whiteColor]]; // 设置导航栏上的标题的颜色、字体 [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor redColor],NSFontAttributeName:[UIFont systemFontOfSize:18]}]; // 取消透明度 [[UINavigationBar appearance] setTranslucent:NO]; // 设置背景图片(前面已经设置了颜色,此处可以不设置,避免覆盖掉上面的颜色) [[UINavigationBar appearance] setBackgroundImage:xxx forBarMetrics:UIBarMetricsDefault]; // 去掉导航栏与内容之间的分割线 [self.navigationController.navigationBar setShadowImage:nil];
2、设置tabbar相关
[[UITabBar appearance] setTintColor: [UIColor blueColor]]; //Normal [[UITabBarItem appearance] setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12],NSBackgroundColorAttributeName:[UIColor greenColor]} forState:UIControlStateNormal]; //Selected [[UITabBarItem appearance] setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15],NSBackgroundColorAttributeName:[UIColor redColor]} forState:UIControlStateSelected]; // 设置tabbar上的图片不要用tintcolor,使用图片原生的样子 UIImage *normalImg = [[UIImage imageNamed:@"xxx"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; vc.tabBarItem.image = normalImg; UIImage *selectImg = [[UIImage imageNamed:@"xxx"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; vc.tabBarItem.selectedImage = selectImg; // 将tabbar的颜色设置为黑色 self.tabBar.barTintColor = [UIColor blackColor];