父子控制器中的自定义导航栏

提到自定义导航栏,大家首先想到的就是自己写个自定义导航控制器,然后设置自己的导航控制器的主题。再把包装着自己控制器的导航控制器的class填上自己写的自定义nav如果遇到个别控制器的导航栏想与众不同,就再写个自定义nav然后再弄个新的导航控制器包裹自己。

可是,如果一个项目中用到了 父子控制器,上面的这种做法就会没有效果。原因就是取不到导航栏。

比如我做的大概架构是一个collectionView的循环引用,让一个个tableview都是包装在我的collectionViewcell里面的,然后里面的的tableview的cell点击之后会push一个新的界面。这时候不管你把这个push的新界面怎么设置导航栏样式 在程序中都是看不见的,因为只能看到最上层,就是collectionViewController的导航栏。

(这里暂时就没截图了,因为好多种结果,截太麻烦了,相信大家能理解文字的意思)

而且就算设置导航栏的主题大家也都知道,这段代码也都是写在首次调用本类时方法里

+ (void)initialize
{
    // 设置导航栏的主题
    UINavigationBar *navBar = [UINavigationBar appearance];
    [navBar setBarTintColor:[UIColor redColor]];
}

之后再想在动态修改,导航栏的背景色或是背景图片都是改不了了,只有在一加载时就写好。我曾试过在push出新的控制器和pop弹栈之后发出通知在这里更改样式,但是都是无效的,改不了。

如图,这个里面控制器是两个scrollView,一个是标题栏scrollView,一个是下面的内容也是一个scrollView。 (之所以用scrollview是为了每个页面懒加载,性能更好),然后在scrollView中嵌套了一个个tableViewController。 是把tableViewController的view加到 scrollView的subViews里。

scrollView是主控制器view的subView 那这个tableViewController的view就是主控制器的 subView的subView。

这里要说一下关于父子控制器的注意点就是:如果把A的view加到了B的view的subViews里 那这个A的控制器也必须加到这个B的控制器的childControllers里。

不然view过去了控制器却没有 他不就是没人管了?

上面这个效果 主要用到了一个方法就是导航栏的隐藏方法

当然在设置界面的时候,上面的箭头和跟帖都是要自己自定义的一个普通的view不是导航栏,可以把他当作导航栏来使用。点击返回会把栈顶控制器弹栈,点击跟帖会再push一个评论控制器。

然后再这个详情控制器将要显示时把导航栏隐藏,再在这个详情页将要弹栈时设置导航栏显示就好。

- (void)viewWillAppear:(BOOL)animated
{
    [self.navigationController setNavigationBarHidden:YES animated:YES];
}
- (IBAction)backBtnClick:(id)sender {
    [self.navigationController popViewControllerAnimated:YES];
    [self.navigationController setNavigationBarHidden:NO animated:YES];
}

这里还有个注意点就是 要把导航栏隐藏写在合适的方法里,如果写在将要跳转的方法prepareForSegue里就会有抽搐的bug

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.destinationViewController isKindOfClass:[SXDetailController class]]) {

        NSInteger x = self.tableView.indexPathForSelectedRow.row;
        SXDetailController *dc = segue.destinationViewController;
        dc.newsModel = self.arrayList[x];
        [self.navigationController setNavigationBarHidden:YES animated:YES];
    }else{
        NSInteger x = self.tableView.indexPathForSelectedRow.row;
        SXPhotoSetController *pc = segue.destinationViewController;
        pc.newsModel = self.arrayList[x];
        [self.navigationController setNavigationBarHidden:YES animated:YES];
    }

}

如图这个是反面教材,仔细看导航栏有个抽搐的bug

有的人可能会尝试干脆直接不用导航控制器了 自己设置按钮控制push和pop

但是这样系统是不允许的 会报错,报错的大概意思就是 你不能给一个没有导航控制器的控制器添加push操作。

我上面用的方法是虽然把导航控制器隐藏了,但他的功能还在。

隐藏导航栏非常好用,可是会遇到一个问题,就是隐藏了导航栏之后,push出的界面无法向左滑动返回。

这个问题类似于: 在导航栏的左上角自定义了一个返回按钮把原本的返回按钮给覆盖了。导致无法实现滑动返回

解决方案是这样,再将控制器push的代码之后 或者在prepareForSegue 方法里面加上这行代码

 if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
            self.navigationController.interactivePopGestureRecognizer.delegate = nil;
        }

因为你覆盖了系统的返回按钮,系统将会通过代理禁用这个滑动返回功能,你提前把代理给踢了,这样滑动返回功能就能报住了。

为了安全起见 最好把主控制器的即将显示加上这行代码

- (void)viewWillAppear:(BOOL)animated
{
    [self.navigationController setNavigationBarHidden:NO animated:YES];
}

如果不加这行代码 可能你一push再拉回来导航栏还是隐藏着的。因为刚才我们只在返回按钮触发时设置了导航栏显示对吧。

最终效果可以达到这样如图

哪里觉得不对劲或者哪里觉得看不懂 欢迎与我交流 欢迎关注我

时间: 2024-10-26 14:35:31

父子控制器中的自定义导航栏的相关文章

自定义导航栏标题按钮

自定义标题栏按钮 @implementation SNTitleButton - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { //图片居中 self.imageView.contentMode = UIViewContentModeCenter; //字体居右 self.titleLabel.textAlignment = NSTextAlignmentRight; //字体

实际iOS编程中遇到的自定义导航栏按钮,导致手势返回失效的解决方法

1\在实际编程过程中往往需要自定义导航栏上面的按钮,也就用: - (instancetype)initWithCustomView:(UIView *)customView; 但用了这个方法后可能会导致iOS7,8的手势返回失效,解决方法就是在自定义的导航栏的viewDidLoad方法中添加如下代码 注意:只有用系统的导航栏,或者继承于系统的导航栏才可以用Push方法,并且自带返回手势. - (void)viewDidLoad { [super viewDidLoad]; __weak type

自定义导航栏按钮 baseViewController中写!

// 自定义导航栏"返回按钮" - (void)initNaviBackBtn {     UIButton *backBtn = [UIButtonbuttonWithType:UIButtonTypeCustom];     backBtn.frame = CGRectMake(0, 0, 50, 22);     [backBtn setImage:[UIImageimageNamed:@"backBtn"] forState:UIControlStateNo

iOS 自定义导航栏笔记

一.UINavigationBar的结构 导航栏几乎是每个页面都会碰到的问题,一般两种处理方式:1.隐藏掉不显示 2.自定义 1. 添加导航栏 TestViewController * mainVC = [[TestViewController alloc] init]; UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:mainVC]; self.window.ro

ios7以上自定义导航栏标题的字体大小及颜色的方法

自定义导航栏的字体和颜色,只需要自定义一个lable,然后将lable添加到导航栏的titleview中就可以了 代码如下 UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,0,0)];//这个frame是初设的,没关系,后面还会重新设置其size. [label setNumberOfLines:0]; UIFont *font = [UIFont fontWithName:@"Arial" size:17]

自定义导航栏

1.设置导航栏样式 [self.navigationBar setBackgroundImage:[UIImage imageNamed:@"navibarbackground"] forBarMetrics:UIBarMetricsDefault]; [self.navigationBar setTintColor:[UIColor whiteColor]];//BarItem颜色 NSShadow *shadow = [NSShadow new]; shadow.shadowCol

分别用ToolBar和自定义导航栏实现沉浸式状态栏

一.ToolBar 1.在build.gradle中添加依赖,例如: compile 'com.android.support:appcompat-v7:23.4.0' 2.去掉应用的ActionBar.可以是修改主题theme为"NoActionBar",例如: <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> 或者不修改主题为"NoAct

IOS 自定义导航栏标题和返回按钮标题

IOS中自定义导航栏标题: UILabel *titleText = [[UILabel alloc] initWithFrame: CGRectMake(160, 0, 120, 50)]; titleText.backgroundColor = [UIColor clearColor]; titleText.textColor=[UIColor whiteColor]; [titleText setFont:[UIFont systemFontOfSize:17.0]]; [titleTex

关于自定义导航栏的那些事儿 UINavigationController

本文只是把我看到的关于自定义导航栏的一些资料搜集了一下 自定义导航栏样式的方法有两种: 1.通过 [UINavigationBar apperance]  来给整个应用上的所有的navigationbar添加样式,这是一个全局的样式设置. 2.当然如果你想要给当前的某一特定的navigationbar添加特定样式就可以通过self.navigationController.navigatinoBar 找到当前bar实例,再进行样式设置. 第二种方法,想必大家都知道,相关资料一搜一大把,不累赘了.