IOS导航栏的问题
ios 两个状态栏 背景图片不一样 push过去正常显示
返回(pop)回来,当前的背景图变成了push过去的那个导航栏的背景图片.
用图片演示:
1.这是控制器A:
2.设置push过去的控制器B:
3.点击返回
后的控制器A:
为什么控制器A的导航栏的背景图片变成了控制器B的?如何修改?
代码奉上:自定义控制器
的所有代码:
#import "LMSNavigationController.h"
@interface LMSNavigationController ()
@end
@implementation LMSNavigationController
- (void)viewDidLoad {
[super viewDidLoad];
[self.navigationBar setTitleTextAttributes:
@{NSFontAttributeName:[UIFont systemFontOfSize:16]}];
}
/**
* 在这个方法中拦截所有push进来的控制器
*/
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (self.childViewControllers.count > 0) {
// 如果push进来的不是第一个控制器
UIButton *leftBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[leftBtn setImage:[UIImage imageNamed:@"nav-back.png"] forState:UIControlStateNormal];
[leftBtn setImage:[UIImage imageNamed:@"nav-back-hi.png"] forState:UIControlStateHighlighted];
leftBtn.frame = CGRectMake(0, 0, 30, 30);
[leftBtn addTarget:self action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:leftBtn];
// 隐藏tabbar
viewController.hidesBottomBarWhenPushed = YES;
}
//把导航栏底部的横线去掉
[self.navigationBar setShadowImage:[UIImage new]];
// 这句super的push要放在后面, 让viewController可以覆盖上面设置的leftBarButtonItem
// 意思是,我们任然可以重新在push控制器的viewDidLoad方法中设置导航栏的leftBarButtonItem,如果设置了就会覆盖在push方法中设置的“返回”按钮,因为 [super push....]会加载push的控制器执行viewDidLoad方法。
[super pushViewController:viewController animated:animated];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
控制器A关键代码:
- (void)viewDidLoad {
[super viewDidLoad];
//导航栏透明背景(nav-clearcolor-image是一张透明的图片)
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"nav-clearcolor-image"] forBarMetrics:UIBarMetricsDefault];
//把导航栏底部的横线去掉
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
//不显示文字
self.navigationItem.title = nil;
}
控制器B关键代码:
- (void)viewDidLoad {
[super viewDidLoad];
UILabel *titleLabel = [[UILabel alloc]init];
titleLabel.text = @"push过来的控制器";
titleLabel.textColor = TitleTextColor;
[titleLabel sizeToFit];
self.navigationItem.titleView = titleLabel;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是个关于
UINavigationController
(假设你们的LMSNavigationController
是它的子类)以及UIViewController
(后文简称 VC )生命周期的问题。。。简单版本的答案
把 VC A 的
viewDidLoad
改成viewWillAppear
。(下面还有个感觉上更优的办法。)
复杂版本(也杂不到哪去。。。)
先看看文档对 viewDidLoad 是怎么描述的:
在 VC 的视图加载进内存的时候,这个方法会被调用。VC B
pop
出去的时候不符合调用 VC A 的viewDidLoad
的条件,解释如下:UINavigationController
维护着一个 VC 栈,你push
、pop
那些 VC 时都是在操作这个栈。push
的时候它会创建一个新的 VC 压入栈中,就是你的 VC B,这个过程中这个新的 VC B 绑定的view
经历了被加入内存的过程,viewDidLoad
被调用。 VC B 处于栈顶,成为topViewController
。 VC A 不再处于栈顶,但仍处于栈中,与它关联的view
仍在内存中。再pop
VC B 出去的时候,VC A 关联的 view 的viewDidLoad
不再被调用。所以
push
pop
具体调用了什么?上图
Figure 1-5 Messages sent during stack changes
图片来源:Navigation Controller 文档的 Monitoring Changes to the Navigation Stack 部分
以
push
VC B 出去为例:VC B 作为当前的 Topmost view controller ,其
viewWillDispear
最先被调用VC A 的
viewWillAppear
被调用UINavigationControllerDelegate
的navigationController:willShowViewController:animated:
被调用转场动画(完成?不清楚)
VC B 的
viewDidDispear
被调用VC A 的
viewDidAppear
被调用UINavigationControllerDelegate
的navigationController:didShowViewController:animated:
被调用综上, VC A 的
viewDidLoad
改成viewWillAppear
即可。然而个人感觉更好的办法是把两个
viewDidLoad
都拆了,逻辑重写在UINavigationControllerDelegate
的navigationController:willShowViewController:animated:
中。即可在一个位置解决改背景图这个需求。完。
更新,上面说的用
UINavigationControllerDelegate
的办法:viewWillAppear
也试了,跟这个一模一样,没出现黑框。就这个问题而言,这两个地方就是符合你要求的。怎么选看自己喜欢就好。系统自带的导航控制器在动画开始前已经做完了该做的事,不会出现动画到一半图片才载入完。最差也就是动画开始前卡住几秒,载入完才开始。
你们的导航控制器是自己定制的,检查定制的部分哪里有问题导致的黑框。
(另。。还是没看到背景图在哪改了。不是第一个控制器那里改的是按钮图片啊)
nav 下的所有 VC 是通用同一个 navBar 的
你在进入 B 的时候修改了 navBar
但是在退出 B 的时候没有改回来
你有2个导航栏控制器 (pop)回去的导航栏是跟当前的导航栏一样的,应该搞个代理就重新赋值就可以了。(不过比较麻烦)
你肯定在B中修改了导航条的色或者图了吧
在A的viewWillAppear方法里面再设置一遍vc的背景图片试试