目标
实现仿淘宝详情的头部滑动渐变透明效果。
关键技术点
是navigationBar
的backgroundImage属性。
从reveal中可以看到navigationbar的frame是(0,20,375,44)
。但是navigationbar的backgroundImage却是从(0,-20)
开始的,如果换成相对viewController的坐标,那么backgroundImage的frame是(0,0,375,64)
。所以设置navigationBar的backgroundImage就可以实现navigationBar和statusBar一起变色的效果。
注意:设置backgroundColor并没有效果
下图是设置了navigationbar的backgroundColor为红色时的reveal效果图。可以明显的看到只是影响了(0,20)
开始的区域,并没有影响从(0,0)
开始,但是注意,如果想要实现navigationBar和statusBar透明的效果,需要将navigationbar的backgroundColor设置为[UIColor clearColor]
.
观察scrollView的contentOffset
属性,实现滑动渐变
这个没啥好说的,KVO
,直接上代码
// kvo
[mainWebView.scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
if ([object isEqual:mainWebView.scrollView] && [keyPath isEqualToString:@"contentOffset"]) {
[self refreshNavigationBar];
}
}
refreshNavigationBar中的实现以及切纯色图的方法:
- (void)refreshNavigationBar{
// 示例中使用了webView
CGPoint offset = mainWebView.scrollView.contentOffset;
// 通过offset.y与固定值300的比例来决定透明度
CGFloat alpha = MIN(1, fabs(offset.y/300));
// 设置translucent为NO来消除alpha为1时的系统优化透明
[self.navigationController.navigationBar setTranslucent:!(BOOL)(int)alpha];
UIColor *realTimeColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:alpha];
UIImage *realTimeImg = [self UINavigationBarImageWithColor:realTimeColor];
[self.navigationController.navigationBar setBackgroundImage:realTimeImg forBarMetrics:UIBarMetricsDefault];
// 消除阴影
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
}
// 获取navigationBar和statusBar的总高度
- (UIImage *)UINavigationBarImageWithColor:(UIColor *)aColor{
CGSize navigationBarSize = self.navigationController.navigationBar.frame.size;
CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
return [self imageWithColor:aColor Size:CGSizeMake(navigationBarSize.width,navigationBarSize.height + statusBarSize.height)];
}
// 绘制纯色图
- (UIImage *)imageWithColor:(UIColor *)aColor Size:(CGSize)aSize{
UIGraphicsBeginImageContextWithOptions(aSize, NO, 0);
[aColor set];
UIRectFill(CGRectMake(0, 0, aSize.width, aSize.height));
UIImage *renderedImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return renderedImg;
}
为了不影响其它页面,记得在离开当前vc的时候将观察去除,将backgroundImage置nil,将默认的透明加上(如果需要的话)。
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:nil];
[self.navigationController.navigationBar setTranslucent:YES];
[mainWebView.scrollView removeObserver:self forKeyPath:@"contentOffset"];
最终效果
总结下:
要实现UINavigationBar+UIStatusBar
渐变透明的效果,需要步骤如下:
- 消除
navigationbar
的其它颜色,透明属性影响 - 实现
navigationBar+statusBar
自定义颜色(纯色图) - 添加
KVO
,实现颜色跟随滚动变化。 - 在离开vc的时候记得将一切恢复原样