前言
今天遇到一个设置 UINavigationBar 返回的问题,发现对UINavigationBar的使用还是有很多问题,所以今天整理了一下。(以下只是个人理解)
1.关于UINavigationBar 设置 translucent 属性
当我们在实现以下代码的时候,
translucent 默认属性为TRUE , 以下为界面 TRUE 和 FALSE 不同的效果。
通过效果我们可以看到translucent 是设置 UINavigationBar 透明显示的,但是其对UIViewController有很大的影响。影响UIViewController 在手机显示的整体区域,但是这里要注意的是 UIViewController 的frame 高度是不会变的(我在UIViewController 添加的按钮的 Y 值为 height - 100),所以这里大家使用的时候一定要注意。
2.如何隐藏UINavigationBar 返回字体
+(void)load{
//runtime 函数替换
[[self class] zxlSwizzleMethod:@selector(viewDidLoad) swizzledSelector:@selector(replace_viewDidLoad)];
}
- (void)replace_viewDidLoad{
[self replace_viewDidLoad];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleDone target:nil action:nil];//隐藏返回按钮跟随的字体
}
其他的设置多多少少会有一些坑,大家就不要走弯路了。
3.如何设置UINavigationBar 返回按钮图片
[UINavigationBar appearance].backIndicatorImage = [[UIImage imageNamed:@"Titlebackbg.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[UINavigationBar appearance].backIndicatorTransitionMaskImage = [[UIImage imageNamed:@"Titlebackbg.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
4.获取UINavigationBar 返回按钮的点击事件
头文件实现协议
@protocol ZXLBackButtonHandlerProtocol <NSObject>
@optional
// Override this method in UIViewController derived class to handle 'Back' button click
-(BOOL)navigationShouldPopOnBackButton;
@end
@interface UIViewController (Extension)<ZXLBackButtonHandlerProtocol>
@end
.m文件实现如下:
@implementation UINavigationController (JLBExtension)
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
if([self.viewControllers count] < [navigationBar.items count]) {
return YES;
}
BOOL shouldPop = YES;
UIViewController* vc = [self topViewController];
if([vc respondsToSelector:@selector(navigationShouldPopOnBackButton)]) {
shouldPop = [vc navigationShouldPopOnBackButton];
}
if(shouldPop) {
dispatch_async(dispatch_get_main_queue(), ^{
[self popViewControllerAnimated:YES];
});
} else {
for(UIView *subview in [navigationBar subviews]) {
if(0. < subview.alpha && subview.alpha < 1.) {
[UIView animateWithDuration:.25 animations:^{
subview.alpha = 1.;
}];
}
}
}
return NO;
}
@end
代码出处 //https://github.com/onegray/UIViewController-BackButtonHandler
5.设置 UINavigationBar 透明
在App的实际应用场景中设置顶部透明然后,返回或者下一界面的时候又不透明,最好的使用方式是在一开始的时候设置navigationController的UINavigationBar为透明。 然后创建一个App中统一使用的基类ViewController,其他的界面继承ViewController。设置统一的顶部颜色为白色,然后设置你想要的场景界面为透明。 这样在使用手势返回的时候就是这样的效果,没有闪动的效果了。但是这样势必会带来一个问题就是App中所有的界面计算Y起始位置的时候要从 [[UIApplication sharedApplication] statusBarFrame].size.height 加上navigationBar的高度开始布局。 界面展示区域也就是 ViewController高度减去 ([[UIApplication sharedApplication] statusBarFrame].size.height + self.navigationController.navigationBar.frame.size.height)。 不过个人觉得这种方式是还是值得推荐的,因为这样你就可以在当前界面的快速实现不同样式的title而不影响其他界面的样式。但是弊端是顶部区域由于有navigationBar,所以此区域是不能点击的。如果一定要使用顶部navigationBar再做其他处理。
6.关于电池栏类型设置 preferredStatusBarStyle 返回
在应用场景中经常会出现,顶部电池栏颜色更换的需求。首页在要变颜色的
ViewController 中实现以下代码
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
然后实现UINavigationController 的扩展类如下(一定要做,不然没有效果)
@implementation UINavigationController (Extension)
- (UIViewController *)childViewControllerForStatusBarStyle{
return self.visibleViewController;
}
@end
UINavigationController不会将 preferredStatusBarStyle方法调用转给它的子视图,而是由它自己管理状态,而且它也应该那样做。因为UINavigationController 包含了它自己的状态栏
,因此就算 UINavigationController中的viewController 实现了 preferredStatusBarStyle方法也不会调用,所以一定要实现UINavigationController 扩展。(很重要)
7.返回按钮不同样式变换
UINavigationBar 上面的返回按钮替换图片是很麻烦的,而且不管怎么设置都没有很好的效果。所以我们这里直接考虑添加 leftBarButtonItem 来替换当前界面的返回按钮。
但是当我们替换后就会发现,leftBarButtonItem 和 UINavigationBar上的返回按钮位子和点击区域是不同的,leftBarButtonItem 是往右偏移一点的。(leftBarButtonItem 往右偏移怎么处理?)代码中借鉴(https://github.com/spicyShrimp/iOS-11-UINavigationItem-SXFixSpace ) 处理偏移问题,不过修改了更换图片的偏移位子。
前一个界面
下一个界面 (要更换的界面)
滑动时渐变效果
以上处理完美解决返回按钮样式更换问题。
文中使用的Dome 地址如下
代码传送门