博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
动态修改UINavigationBar的背景色
阅读量:4513 次
发布时间:2019-06-08

本文共 3297 字,大约阅读时间需要 10 分钟。

这是我们最终想要得到的效果:demo

思路

UISrollView的delegate方法 - (void)scrollViewDidScroll:(UIScrollView *)scrollView中根据当前的contentOffset更新navigationBar的backgroundColor即可,so easy~

开动

那么我们来看看apple为我们提供了哪些API来设置navigationBar的颜色。

首先想到的是最常用的[UINavigationBar appearance],我们一般会在AppDelegate中使用它对navigationBar进行统一的设置。但是如果试一下,会发现在scrollViewDidScrollView中调用它并不能动态地改变navigationBar的颜色,原因可以看一下Apple的doc:

Use the UIAppearance protocol to get the appearance proxy for a class. You can customize the appearance of instances of a class by sending appearance modification messages to the class’s appearance proxy.

但是:

iOS applies appearance changes when a view enters a window, it doesn’t change the appearance of a view that’s already in a window. To change the appearance of a view that’s currently in a window, remove the view from the view hierarchy and then put it back.

所以换一条路,直接修改UINavigationBar的backgroudColor:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{    UIColor *color = [UIColor blueColor];    CGFloat offsetY = scrollView.contentOffset.y; if (offsetY > 0) { CGFloat alpha = 1 - ((64 - offsetY) / 64); self.navigationController.navigationBar.backgroundColor = [color colorWithAlphaComponent:alpha]; } else { self.navigationController.navigationBar.backgroundColor = [color colorWithAlphaComponent:0]; } }

结果却是。。。仔细观察,会发现navigationBar的高度是44,它的上方是statusBar,而且,navigationBar的上面还有一个未知的View。。。到底Apple是怎么实现UINavigationBar的呢,让我们一探究竟!

在xcode的顶部菜单栏找到Debug > View Debugging > Capture View Hierarchy:

原来UINavigationBar上有一个_UIBackDropView,正是它决定了navigationBar的背景色。

那么我们是不是可以修改它的颜色呢,赶紧打开UINavigationBar.h,找了一圈,?

既然没有public的API,我们只能hack了!

Hack

我们的思路很简单,参照Apple的实现,在navigationBar的view hierarchy中插入一个view,通过它来控制在navigationBar的backgroundColor。

考虑到继承UINavigationBar使用起来会非常不便,我们决定用Category来实现,首先定义我们的category:

@interface UINavigationBar (BackgroundColor)- (void)lt_setBackgroundColor:(UIColor *)backgroundColor; @end

实现:我们使用associatedObject将overlayView动态地绑定到UINavigationBar的instance上,当调用lt_setBackgroundColor的时候,我们只要更新这个overlayView就行啦~

@implementation UINavigationBar (BackgroundColor)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]; // insert an overlay into the view hierarchy self.overlay = [[UIView alloc] initWithFrame:CGRectMake(0, -20, [UIScreen mainScreen].bounds.size.width, self.bounds.size.height + 20)]; self.overlay.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; [self insertSubview:self.overlay atIndex:0]; } self.overlay.backgroundColor = backgroundColor; } @end

最后在scrollViewDidScroll中,我们就可以动态地修改UINavigationBar的backgroundColor了:

[self.navigationController.navigationBar lt_setBackgroundColor:[color colorWithAlphaComponent:alpha]];

完整的代码在这里:

写在最后

UINavigationBar是一个比较特殊的view,它被系统高度集成,有时候定制起来并不那么方便。其实这个demo完全可以用另外一种方法实现,就是不用UINavigationBar,自己画一套UI。

很多时候我们都会发现系统原生控件出现一些预料之外的行为,那么打开view debugging,找出原因,然后解决它!

转自:http://tech.glowing.com/cn/change-uinavigationbar-backgroundcolor-dynamically/

 

转载于:https://www.cnblogs.com/mumoozhu/p/4548578.html

你可能感兴趣的文章
RocketMQ服务搭建_1
查看>>
CentOS7 安装 Docker
查看>>
Redis常见问题
查看>>
Android自带样式
查看>>
iSCSI 原理和基础使用
查看>>
Gym101350 J Lazy Physics Cat
查看>>
Java读取文件方法大全
查看>>
解决mysql无法显示中文/MySQL中文乱码问号等问题
查看>>
CentOS 7.2 配置mysql5.7
查看>>
第一次写博客用来记录自己的工程师生涯。
查看>>
python输出转义字符
查看>>
java基础43 IO流技术(输入字节流/缓冲输入字节流)
查看>>
ASP.NET那点不为人知的事(四)
查看>>
☆ [HNOI2012] 永无乡 「平衡树启发式合并」
查看>>
git 常用命令
查看>>
Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验,使用消息资源文件对消息国际化...
查看>>
ES6--4.解构赋值
查看>>
CCF系列之图像旋转(201503-1)
查看>>
edit.h 再转换到 VS2010 的问题
查看>>
POJ 3134 Power Calculus ★(记录状态的BFS)
查看>>