iOS 自定义导航--参照系统导航

不以图片开头的文章都不是好文章

与世无争.JPG

任何时候,都不要迷失自己。有一双清澈的眼睛,可以沉默,但不要迷离方向;有一颗干净的心灵,可以容纳,但不能承载太多;有一个优雅的姿态,可以美丽,但不要沉溺世事。其实,一切源于自然,源于清净,源于灵魂的修行。

现状描述:

一般项目中大概都是一个tabbar管理几个带导航的控制器,可其中有几个控制器没有导航。这时候就需要进入该控制器的时候隐藏导航,离开的时候显示导航。

大概流程就是设置代理 self.navigationController.delegate = self;
遵守协议 UINavigationControllerDelegate

#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:YES animated:YES];
}

并在viewWillAppear中隐藏

[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];

viewWillDisappear中显示导航,设置回导航,例如:

UIImage *image= [self createImageWithColor:kMainColor];
[self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
//其中:createImageWithColor:是根据传递主题颜色生成图片
/*
- (UIImage *)createImageWithColor:(UIColor*)color {
    CGRect rect = CGRectMake(0, 0, 1.0f, 1.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context =  UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);
    UIImage *image =  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}*/
发现Bug:

以上这种写法,一般也不会有啥问题。除非遇到跳转的界面也是隐藏导航的,这时候有概率出现该显示导航的却消失了(复现过程:滑动来回调用viewWillAppearviewWillDisappear

脑袋瓜子嗡嗡的.jpg

构思解决方案:

所以干脆让导航一直都是隐藏状态,显示的时候添加自定义的导航View,当然功能都参照着系统的功能

实施大致过程关键Code:
  • 初始化 懒加载控件
- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self initView];
    }
    return self;
}

- (void)initView {
    self.backgroundColor = [UIColor redColor];///kMainColor;
    //根据公开传递的参数按需增加
    //默认加载灰色的线
    [self bottomGrayLine];
    [self backBtn];
}
  • 返回按钮
/// 返回按钮 默认添加 参照leftBarButtonItem
- (JYDisableHightlightBtn *)backBtn {
    if (!_backBtn) {
        _backBtn = [JYDisableHightlightBtn buttonWithType:(UIButtonTypeCustom)];
        [self addSubview:_backBtn];
        //Masonry约束
        [_backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(15);
            make.width.equalTo(80);
            make.height.equalTo(44);
            make.bottom.equalTo(0);
            
        }];
        _backBtn.backgroundColor = [UIColor blueColor];
        [_backBtn setImage:[UIImage imageNamed:@"common_back"] forState:(UIControlStateNormal)];
        //按钮图片居左
        _backBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
        //点击响应RAC传递信号
        [[_backBtn rac_signalForControlEvents:(UIControlEventTouchUpInside)] subscribeNext:^(__kindof UIControl * _Nullable x) {
            if (self.leftBtnClickedBlock) { //使用block自定义返回或返回根视图
                self.leftBtnClickedBlock();
            }else {
                [self.viewController.navigationController popViewControllerAnimated:YES];
            }
        }];
    }
    return _backBtn;
}
  • 中间的标题
//中间的标题
- (UILabel *)titleLabel {
    if (!_titleLabel) {
        _titleLabel = [[UILabel alloc]init];
        [self addSubview:_titleLabel];
        [_titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerX.equalTo(self.mas_centerX);
            make.bottom.equalTo(-10);
        }];
        _titleLabel.backgroundColor = [UIColor blueColor];
        _titleLabel.font = [UIFont systemFontOfSize:18];
        _titleLabel.textColor = [UIColor whiteColor];
    }
    return _titleLabel;
}
  • 在头文件中公开属性,方便设置导航按钮等,如:
//背景
@property (nonatomic, copy) NSString *jy_naviImageName; //titleView
@property (nonatomic, assign) BOOL jy_hideBottomGrayLine;
//左边
@property (nonatomic, copy) void (^leftBtnClickedBlock)(void); //left
@property (nonatomic, assign) BOOL jy_hiddenBackBtn;

@property (nonatomic, copy) void (^leftBtnsClickedBlock)(UIButton *leftBtns); //lefts需要

//中间
@property (nonatomic, copy) NSString *titleString;
@property (nonatomic, copy) NSString *titleImageString;
  • 当然还要仿照系统UINavigationItem还有titleViewrightBarButtonItemrightBarButtonItems以及是否隐藏返回按钮,右侧是否可点击等等

  • 最后在基类中隐藏导航并添加自定义导航视图,后续创建的控制器需要继承自该基类
/*
 设置父类的导航代理,隐藏导航,并添加自定义导航
 */
#import "JYBaseViewController.h"

@interface JYBaseViewController ()<UINavigationControllerDelegate>

@end

@implementation JYBaseViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationController.delegate = self;
    self.baseNaviView = [[JYNaviView alloc]initWithFrame:CGRectMake(0, 0, ScreenWidth, k_Height_NavBar)];
    [self.view addSubview:self.baseNaviView];
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:YES animated:YES];
}

#pragma mark - dealloc
- (void)dealloc{
    NSLog(@"%@--dealloc", [self className]);
}
整合到项目中实际遇到的问题:
  1. UISearchControllersearchBar点击的时候会跑到顶部
    解决办法:个人建议直接使用UISearchBar设置样式后调用原来的逻辑。
  2. 同一个界面直接显示和配合WMPageController使用。
    解决办法:在其中任意一个推出界面时增加type属性(或成员变量),根据属性来判断是否隐藏导航视图。如:
初始化赋值type,枚举最好,此处简写
- (instancetype)initWithWMPage:(NSInteger)type {
    if (self = [super init]) {
        _type = type;
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    if (self.type == 1) {
        self.baseNaviView.hidden = YES;
    }else {
        self.baseNaviView.titleString = @"微视频";
        self.baseNaviView.hidden = NO;
    }
    //...

    CGFloat startY = self.baseNaviView.hidden ? 0 : CGRectGetMaxY(self.baseNaviView.frame);
    CGFloat videoH = self.baseNaviView.hidden ? ScreenHeight - self.tabBarController.tabBar.height- k_Height_NavBar - 41 : ScreenHeight- k_Height_NavBar- k_Height_Bottom;
    self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, startY, ScreenWidth, videoH) style:(UITableViewStylePlain)]; //只有导航没有tabbar,刘海屏系列减34,非减0
}
  1. 有的界面不显示自定义的导航视图
    解决办法:查看视图层级,如果被遮挡那就带到最前方[self.view bringSubviewToFront:self.baseNaviView];

  2. 子视图被遮挡
    解决办法:如果是代码创建的视图,那么创建的时候CGRectMake的Y参数使用CGRectGetMaxY(self.baseNaviView.frame)或者k_Height_navBar,高度看情况是否需要再减掉。如果是Xib拖的控件,那么建议top约束到superView而不是Safe Area,然后在控制器中self.safeToTop.constant = k_Height_NavBar;

  3. 执行Block会警告:Capturing 'self' strongly in this block is likely to lead to a retain cycle
    解决办法:建议导入RAC框架或YYCategories,创建弱引用self

    @weakify(self)
    self.baseNaviView.leftBtnClickedBlock = ^{
        @strongify(self)
        [self.navigationController popToRootViewControllerAnimated:YES];
    };

...

  • BTW:Demo
    烦恼都忘掉.JPG
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容