目標
實現仿淘寶詳情的頭部滑動漸變透明效果。
關鍵技術點
是navigationBar
的backgroundImage屬性。
navigationBar的UI結構.png
從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]
.
背景為紅色.png
觀察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"];
最終效果
效果.gif
總結下:
要實現UINavigationBar+UIStatusBar
漸變透明的效果,需要步驟如下:
- 消除
navigationbar
的其它顏色,透明屬性影響 - 實現
navigationBar+statusBar
自定義顏色(純色圖) - 添加
KVO
,實現顏色跟隨滾動變化。 - 在離開vc的時候記得將一切恢復原樣