动态修改UINavigationBar的背景色--by-胡旭
这是我们最终想要得到的效果

思路
在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:
结果却是。。。

仔细观察,会发现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]];
完整的代码在这里:https://github.com/ltebean/LTNavigationBar
写在最后
UINavigationBar是一个比较特殊的view,它被系统高度集成,有时候定制起来并不那么方便。其实这个demo完全可以用另外一种方法实现,就是不用UINavigationBar,自己画一套UI。
很多时候我们都会发现系统原生控件出现一些预料之外的行为,那么打开view debugging,找出原因,然后解决它!
动态修改UINavigationBar的背景色--by-胡旭的更多相关文章
- 动态修改UINavigationBar的背景色
这是我们最终想要得到的效果: 思路 在UISrollView的delegate方法 1 - (void)scrollViewDidScroll:(UIScrollView *)scrollView ...
- iOS 动态修改导航栏颜色 UINavigationBar
示例 所谓动态修改 意思是 在当前页面滚动的过程中 亦或 是在 触发返回事件\进入一个新的页面 导航栏的动态变化 由于系统级别的navBar 高度集成 很多自己想实现的功能 很不好弄 如果是通过 ...
- 动态修改svg的颜色,svg做背景色时候修改颜色
svg修改背景色可以使用fill属性来修改,但是我现在需要动态改变svg的颜色,例如我hover的时候 现在发现一种兼容性还不错的方法是css属性mask 类似于给路径填充上颜色,结合backgrou ...
- ReactNative 根据scrollView/listview滑动距离动态修改NavBar颜色
我们常见某些APP上滑的时候,NavBar颜色会从透明渐变为某种颜色 原理非常简单,根据scrollView的回调动态修改NavBar的透明度即可. 在RN中,尤其是ListView中这个回调不是很好 ...
- ASP.NET中直接用C# 动态修改CSS样式
ASP.NET中直接用C# 动态修改CSS样式 wonsoft (wonsoft@163.com) 使用JavaScript控制CSS样式有点麻烦,还是觉得直接使用C#操作更方便快捷,本文通过两个B ...
- 关于devexpress报表XtraReport,动态修改报表样式(.repx格式),动态添加数据并使用的理解
一.基本概念: XtraReports 中的每个报表都由 XtraRepot 类的一个实例表示,或者由该类的子类来表示(这种情况更常见). 因此,每个报表都作为带区的容器使用,而每个带区中都包含报表控 ...
- 【VS开发】VS2010 MFC中控件、对话框等背景颜色动态修改的方法
[VS开发]VS2010 MFC中控件.对话框等背景颜色动态修改的方法 标签(空格分隔):[VS开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明: ...
- react+antd 使用脚手架动态修改主题色
最近做了一个需求,后台管理系统添加一个可以动态修改ant-design主题色.查询了大多数的文章,发现基本都是抄来抄去,而且文章记录的也一点也不详细.刚刚把这个功能做完了,顺便记录一下如何去修改主题色 ...
- thinkphp 3.2.3 动态修改conf配置文件
thinkphp 3.2.3 的C()方法能修改配置文件,但是是动态修改的,没有真正的更改文件. 我查了网上网友分享的方法,都不怎么合适,我就自己摸索写了一个,配置写到text.php中,我的目录如下 ...
随机推荐
- MySQL 数据操作与查询笔记 • 【第1章 MySQL数据库基础】
全部章节 >>>> 本章目录 1.1 数据库简介 1.1.1 数据和数据库定义 1.1.2 数据库发展阶段 1.1.3 数据库系统组成 1.1.4 关系型数据库 1.2 M ...
- Java面向对象程序设计笔记 • 【目录】
持续更新中- 我的大学笔记>>> 章节 内容 实践练习 Java面向对象作业目录(作业笔记) 第1章 Java面向对象笔记 • [第1章 面向对象] 第2章 Java面向对象笔记 • ...
- 编写Java程序,读取文本文档的内容,去除文本中包含的“广告”字样,把更改后的内容保存到一个新的文本文档中
查看本章节 查看作业目录 需求说明: 读取文本文档的内容,去除文本中包含的"广告"字样,把更改后的内容保存到一个新的文本文档中 实现思路: 在main() 方法中,使用 new F ...
- 编写Java程序,使用List集合和Map集合输出 市和区
如图: 代码: import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java ...
- 2048 双人创新小游戏【JavaFX-FXGL游戏框架】
一个 uml 课程的大作业,项目要求设计并开发一款 2048 与某种游戏类型相结合的创新游戏.可以选择只建模或者既建模又实现,既然要做当然是选择实现啦(虽然没有接触过游戏...期末周的莽冲hhh,小组 ...
- CSS基础 装饰 元素本身隐藏和显示效果及案例
1.visibility:hidden; 2.display: none: 区别: 1.visibility:hidden 隐藏元素本身,且在网页中 占位置 2.display:none; 隐藏元素本 ...
- 初识python: 装饰器
定义: 本质是函数,功能是"装饰"其它函数,即为其他函数添加附加功能原则: 1.不能修改被装饰函数的源代码: 2.不能修改被装饰函数的调用方式实现装饰器知识储备: 1.函数即&qu ...
- spring-Ioc学习笔记
spring 是面向Bean的编程 Ioc (Inversion of Control) 控制反转/依赖注入(DI:Dependency Injection) Aop(Aspect Oriented ...
- vs2017 快捷键 - 总结
1.格式化代码 先选中需要格式的代码,一般是全选[Ctrl+A]后,Ctrl+K+F[按定Ctrl不动,依序点击 K和F,然后再放开 Ctrl ] 2.多行注释 注释: 先CTRL+K,然后CTRL+ ...
- spring security 在controller层 方法级别使用注解 @PreAuthorize("hasRole('ROLE_xxx')")设置权限拦截 ,无权限则返回403
1.前言 以前学习的时候使用权限的拦截,一般都是对路径进行拦截 ,要么用拦截器设置拦截信息,要么是在配置文件内设置拦截信息, spring security 支持使用注解的形式 ,写在方法和接口上拦截 ...