iOS --没事撸一撸控件之UINavigationBar

UINavigationBar,只要是做iOS开发的肯定都碰到过。今天趁着手头的没有砖可搬,好好整理一下。

层级关系

首先写一个简单的UINavigationController,查看视图层级。可以看到下面的层级关系。

F0629251-5F4D-4347-A585-F8B6C7BD390F.png

第一级 UINavigationBar

这没什么好说的,今天的主角。

第二级

_UINavigationBarBackground(UIImageView)

这个对应了bar 的背景图片方法,不过这个属性不属于共有API

- (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarPosition:(UIBarPosition)barPosition barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;

UINavigationButton

这个就是我们自定义的btn

_UINaigationBarBackIndicatorView

这个就是返回按钮,可以自定义图片

@property(nullable,nonatomic,strong) UIImage *backIndicatorImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR __TVOS_PROHIBITED;

第三级 第四级----

这边我们主要来看下系统的_UINavigationBarBackground 下面的层级,
首先,我们看到在第三级别里面有个UIImageView.这个imageview 其实是bar下面的深灰色一条线。
我记得我一个基友,来问我这个问题,说要把下面这条线隐藏。我费了老大的力气,才找到这个私有属性名。看下面代码! 就是这个 _shadowView

 UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[ViewController new]];
    NSArray *arry = [nav.navigationBar subviews];
    for (UIView *view in arry) {
        NSString *viewName = NSStringFromClass([view class]);
        if ([viewName isEqualToString:@"_UINavigationBarBackground"]) {
            UIImageView *line = [view valueForKey:@"_shadowView"];
            line.hidden = YES;
        }
    }
    self.window.rootViewController = nav;

毕竟私有属性,比较好的方法就是用别的view盖住他。但直接使用这个属性隐藏,好像基友的应用也是ok的。

话题有点偏了,我们继续回到正题上。
还有一个_UIBackDropView 和_UIBackdropEffectView
这个其实就是系统加的毛玻璃效果。

我们肯定遇到要设置NavigationBar 背景颜色的时候
如果想平常的空间一样

self.navigationController.navigationBar.backgroundColor = [UIColor blackColor];

那么恭喜你掉坑里了,如何正确设置。以及为什么要这么设置我们下面一一道来。

突变的层级结构

CA7AC3B0-E41E-4D4B-A3D0-32E72777BDD8.png

当我们设置了背景图片,卧槽。第三和第四级的那2个view呢。系统在你设置背景图片的时候自定将有毛玻璃效果的2个层级,从视图上移除。让我们可以清楚的看到背景。
但你设置背景颜色时候,那2个层级还在。不知道苹果baba 是怎么想的。

[self.navigationController.navigationBar setBackgroundImage:[UIImage new]forBarMetrics:UIBarMetricsDefault];
    self.navigationController.navigationBar.backgroundColor = [UIColor redColor];

这样就可以完美的设置背景色了。
其实系统也提供了设置全局bar的方法了

[[UINavigationBar appearance] setBackgroundColor:[UIColor redColor]];

这种也可以成功的bar 的背景色。不过是全局的。

--了解NavigationBar 的层次结构,我们就针对大多数问题 做一个解答。
Q:怎么设置NavigationBar 的背景色
上面已经说过了,就不说啦
Q:我想设置NavigationBar 透明,但我想item不隐藏。
首先我们看下层次结构 ,如果你这样设置

self.navigationController.navigationBar.alpha = NO;

肯定不行,我们知道如果设置背景色,是第二级的_UINavigationBarBackground 来显示的,而UINavationBarButton 和他平级。知道这一点就好做了啊。只要设置_UINavigationBarBackground 的alpha 为0 就可以了。
不过要注意一点,因为苹果没开放这个属性。所以为了安全过过审起见,可以这样设置:

[self.navigationController.navigationBar subViews][0] //这个就是_UINavigationBarBackground 设置透明度就好啦。

Q:我想设置nagationBar 滑动渐变效果
如果我根据滑动的偏移量来设置 _UINavigationBarBackground的透明度。那就掉坑了,还记得3 4层级的毛玻璃效果么,只有当_UINavigationBarBackground 完全透明或者设置背景图片的时候才会隐藏。
这就说明,你滑动的时候毛3 4层级还在,你渐变的效果被3.4 层级覆盖住了。就看不到你想要的效果了。
我们一步一步 来:
首先要去掉3 4 层级 (系统的毛玻璃效果)

[self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
或者
[self.navigationController.navigationBar subViews][0] .alpha = 0;

3 4层级去掉了 渐变效果怎么显示啊!
这时候因为要取消3 4层级 占用了系统自带的设置背景色的view。我们可以自己创建一个view来显示背景色。大体思路就是这样。借用别人的一段代码

static char overlayKey;

- (UIView *)overlay
{
    return objc_getAssociatedObject(self, &overlayKey);
}

- (void)setOverlay:(UIView *)overlay
{
    objc_setAssociatedObject(self, &overlayKey, overlay, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)lt_setBackgroundColor:(UIColor *)backgroundColor
{
    if (!self.overlay) {
        [self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
        self.overlay = [[UIView alloc] initWithFrame:CGRectMake(0, -20, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds) + 20)];
        self.overlay.userInteractionEnabled = NO;
        self.overlay.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
        [self insertSubview:self.overlay atIndex:0];
    }
    self.overlay.backgroundColor = backgroundColor;
}

只要了解了层次结构,大部分的问题都迎刃而解。如果童鞋们,还有什么问题,可以留言,我以后跟新补充。

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