本人有若干成套学习视频, 可试看! 可试看! 可试看, 重要的事情说三遍 包含Java
, 数据结构与算法
, iOS
, 安卓
, python
, flutter
等等, 如有需要, 联系微信tsaievan
.
今天感冒了, 太特么难受了, 写个小 demo 吧
不多说, 先看效果
思路其实很简单,监听 tableView 的滚动范围, 即 contentOffset 的 y 值,
- 当 y 值 = 0时, navigationBar 先隐藏,
- 当 y 刚刚大于0时, navigationBar 出现
- 透明度其实就是 y 值和轮播图高度的比值,这比值是会随之 y值得变动而变动的, 那么我们就可以用这个来设置透明度,
需要注意的点是:
- 要去掉 navigationBar 的底部阴影,这样才不至于出现一条线,影响用户体验
- 当tableView 拖到轮播图下方时, navigationBar 要保持不透明颜色
- 系统设置 navigationBar 时,默认的是半透明状态, 很不爽,所以需要生成一张纯色图,来动态地设置 navigationBar 的背景图
那我们来开始一步步做吧
1. 首先,设置观察者
#pragma mark *** 视图的生命周期 ***
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
/* tableViewController 观察 tableView 的 contentOffset */
[self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
}
2. 当观察者的观察对象的属性一发生变化时, 就调用这个方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if ([object isEqual:self.tableView] && [keyPath isEqualToString:@"contentOffset"]) {
[self refreshNavigationBar];
}
}
3.那么刷新 navigationBar-(void)refreshNavigationBar
是个什么东西呢?
- (void)refreshNavigationBar
{
CGPoint offset = self.tableView.contentOffset;
/* 当 offset.y 值小于0时,状态栏隐藏, 其余时候显示 */
self.navigationController.navigationBarHidden = (offset.y < 0);
/* 在这个页面中, 我的轮播图的宽高比是180:300 */
/* 那么我先算出轮播图的高度 */
CGFloat cycleScrollViewHeight = kScreenWidth * 180 / 300;
/* 用 offset 值比上轮播图的高度,那么,当轮播滚动范围的 y 值等于轮播图的高度时, navigationBar 就完全不透明了 */
CGFloat alpha = MIN(1, fabs(offset.y / cycleScrollViewHeight));
/* 设置 透明度为 NO 来消除 alpha 为1时的系统化透明 */
BOOL translucent = !(int)alpha; /* 也就是说,当tableView 越往下拖, alpha 值为1,navigationBar 的透明度就始终保持不透明 */
[self.navigationController.navigationBar setTranslucent:translucent];
/* 设置实时的颜色 */
UIColor *realTimeColor = [UIColor colorWithRed:0.14 green:0.79 blue:0.67 alpha:alpha];
/* 用实时的颜色生成一张纯色的图片 */
UIImage *image = [self navigationBarImageWithColor:realTimeColor];
[self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
/* 消除阴影 */
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
}
第3步才是核心代码, 很重要,
4.这里面还有一个重要的方法是生成一张纯色图,生成纯色图, 我们需要计算出纯色图的大小, 纯色图的大小实际上就是 navigationBar 的大小和状态栏(statusBar 的大小)
- (UIImage *)navigationBarImageWithColor:(UIColor *)color
{
CGSize navigationBarSize = self.navigationController.navigationBar.frame.size;
CGSize statusBarSize = [[UIApplication sharedApplication]statusBarFrame].size;
return [UIImage yf_imageWithPureColor:color size:CGSizeMake(navigationBarSize.width, navigationBarSize.height + statusBarSize.height)];
}
5.实际上真正生成纯色图的是这个方法:yf_imageWithPureColor:color size:
在这里,我们创造一个 UIImage 的分类,专门生成纯色图.这样,我们在项目的其他任何地方需要根据颜色和大小生成纯色图的时候,都可以调用这个方法
分类方法的实现如下:
+ (UIImage *)yf_imageWithPureColor:(UIColor *)color size:(CGSize)size
{
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
[color set];
UIRectFill(CGRectMake(0, 0, size.width, size.height));
UIImage *renderImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return renderImage;
}