本人有若干成套學習視頻, 可試看! 可試看! 可試看, 重要的事情說三遍 包含Java, 數(shù)據(jù)結構與算法, iOS, 安卓, python, flutter等等, 如有需要, 聯(lián)系微信tsaievan.
今天感冒了, 太特么難受了, 寫個小 demo 吧
不多說, 先看效果

navigationBar 漸變透明效果
思路其實很簡單,監(jiān)聽 tableView 的滾動范圍, 即 contentOffset 的 y 值,
- 當 y 值 = 0時, navigationBar 先隱藏,
- 當 y 剛剛大于0時, navigationBar 出現(xiàn)
- 透明度其實就是 y 值和輪播圖高度的比值,這比值是會隨之 y值得變動而變動的, 那么我們就可以用這個來設置透明度,
需要注意的點是:
- 要去掉 navigationBar 的底部陰影,這樣才不至于出現(xiàn)一條線,影響用戶體驗
- 當tableView 拖到輪播圖下方時, navigationBar 要保持不透明顏色
- 系統(tǒng)設置 navigationBar 時,默認的是半透明狀態(tài), 很不爽,所以需要生成一張純色圖,來動態(tài)地設置 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. 當觀察者的觀察對象的屬性一發(fā)生變化時, 就調(diào)用這個方法
- (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時,狀態(tài)欄隱藏, 其余時候顯示 */
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時的系統(tǒng)化透明 */
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 的大小和狀態(tài)欄(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:
在這里,我們創(chuàng)造一個 UIImage 的分類,專門生成純色圖.這樣,我們在項目的其他任何地方需要根據(jù)顏色和大小生成純色圖的時候,都可以調(diào)用這個方法

創(chuàng)建一個生成純色圖的分類
分類方法的實現(xiàn)如下:
+ (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;
}