示例

所謂動態修改 意思是 在當前頁面滾動的過程中 亦或 是在 觸發返回事件\進入一個新的頁面 導航欄的動態變化
由於系統級別的navBar 高度集成 很多自己想實現的功能 很不好弄 如果是通過繼承的話, 參見 category 類別那章相對來說 更適用,自己開發一些個性自定義的方法去實現想要的功能.
參見http://www.cocoachina.com/ios/20150409/11505.html
這篇文章 就是用類別的方法 拓展了 navigationBar 的實例方法 . 甚至動用了 c 底層. 不過 使用起來還是很方便
上關鍵類別代碼
// // UINavigationBar+MyNavBar.h // LTNavigationBar #import <UIKit/UIKit.h> @interface UINavigationBar (MyNavBar) - (void)lt_setBackgroundColor:(UIColor *)backgroundColor; - (void)lt_setElementsAlpha:(CGFloat)alpha; - (void)lt_setTranslationY:(CGFloat)translationY; - (void)lt_reset; @end // // UINavigationBar+Awesome.m // LTNavigationBar #import "UINavigationBar+MyNavBar.h" #import <objc/runtime.h> @implementation UINavigationBar (MyNavBar) 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]; self.overlay = [[UIView alloc] initWithFrame:CGRectMake(0, -20, [UIScreen mainScreen].bounds.size.width, CGRectGetHeight(self.bounds) + 20)]; self.overlay.userInteractionEnabled = NO; self.overlay.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; [self insertSubview:self.overlay atIndex:0]; } self.overlay.backgroundColor = backgroundColor; } - (void)lt_setTranslationY:(CGFloat)translationY { self.transform = CGAffineTransformMakeTranslation(0, translationY); } - (void)lt_setElementsAlpha:(CGFloat)alpha { [[self valueForKey:@"_leftViews"] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger i, BOOL *stop) { view.alpha = alpha; }]; [[self valueForKey:@"_rightViews"] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger i, BOOL *stop) { view.alpha = alpha; }]; UIView *titleView = [self valueForKey:@"_titleView"]; titleView.alpha = alpha; // when viewController first load, the titleView maybe nil [[self subviews] enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) { if ([obj isKindOfClass:NSClassFromString(@"UINavigationItemView")]) { obj.alpha = alpha; *stop = YES; } }]; } - (void)lt_reset { [self setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault]; [self.overlay removeFromSuperview]; self.overlay = nil; } @end
調用示例 這個效果 透明度的更改也是仿淘寶 展示 具體商品頁面的滑動效果 可以去查看
- (void)viewDidLoad { [super viewDidLoad]; self.tableView.dataSource = self; [self.navigationController.navigationBar lt_setBackgroundColor:[UIColor clearColor]];
[self setBackButtonStyleLight:YES]; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { UIColor * color = [UIColor colorWithRed:0/255.0 green:175/255.0 blue:240/255.0 alpha:1]; CGFloat offsetY = scrollView.contentOffset.y; if (offsetY > NAVBAR_CHANGE_POINT) { CGFloat alpha = MIN(1, 1 - ((NAVBAR_CHANGE_POINT + 64 - offsetY) / 64)); // NAVBAR_CHANGE_POINT 和 64 這兩個參數 都是 看效果需求可酌情更改 就是 透明度變化的時機 系數 [self.navigationController.navigationBar lt_setBackgroundColor:[color colorWithAlphaComponent:alpha]];
[self setBackButtonStyleLight:NO alpha:alpha];
} else { [self.navigationController.navigationBar lt_setBackgroundColor:[color colorWithAlphaComponent:0]];
[self setTitle:@""];
[self setBackButtonStyleLight:YES];
}
}
- (void)setBackButtonStyleLight:(BOOL)isLight { [self setBackButtonStyleLight:isLight alpha:1]; } - (void)setBackButtonStyleLight:(BOOL)isLight alpha:(CGFloat)alpha { if(isLight){ [titleLabel setAlpha:1];//導航標題 [backButton setAlpha:1];//返回按鈕 [titleLabel setText:@""]; UIImage *image = backButton.imageView.image; UIImage *targetImage = [UIImage imageNamed:@"icon_fanhi"]; if(image != targetImage){ [backButton setImage:[UIImage imageNamed:@"icon_fanhi"] forState:UIControlStateNormal]; [backButton setImage:[UIImage imageNamed:@"icon_fanhi"] forState:UIControlStateHighlighted]; } }else{ if(alpha < 0.5){ [titleLabel setText:@""]; UIImage *image = backButton.imageView.image; UIImage *targetImage = [UIImage imageNamed:@"icon_fanhi"]; if(image != targetImage){ [backButton setImage:[UIImage imageNamed:@"icon_fanhi"] forState:UIControlStateNormal]; [backButton setImage:[UIImage imageNamed:@"icon_fanhi"] forState:UIControlStateHighlighted]; } //先是之前的消失 [backButton setAlpha:(0.5 - alpha) * 2]; }else{ UIImage *image = backButton.imageView.image; UIImage *targetImage = [UIImage imageNamed:@"icon_fanhihei"]; if(image != targetImage){ [backButton setImage:[UIImage imageNamed:@"icon_fanhihei"] forState:UIControlStateNormal]; [backButton setImage:[UIImage imageNamed:@"icon_fanhihei"] forState:UIControlStateHighlighted]; } [titleLabel setText:foodItemModel.foodName]; //將返回和分享慢慢出現 CGFloat showAlpha = (alpha - 0.5) * 2; [titleLabel setAlpha:showAlpha]; [backButton setAlpha:showAlpha]; } } }
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:YES]; [self initScrollNav]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; //self.tableView.delegate = nil;//廢棄代碼 [self.navigationController.navigationBar lt_reset];//頁面消失時候要 恢復 正常導航欄模式 } - (void)initScrollNav { self.tableView.delegate = self; [self scrollViewDidScroll:self.tableView]; [self.tableView reloadData]; [self.navigationController.navigationBar setShadowImage:[UIImage new]]; } - (void)dealloc { self.tableView.delegate = nil;//不能在 viewWilldisappear 里nil 這時候 仍然會觸發 scrollViewDidLoad 導致崩潰 需要卸寫在這里 }
還有一種情況 就是滾動過程中 導航欄消失 保留狀態欄 這種情況 一些產品比較青睞 我個人特別不喜歡 一直堅信 ios7以后 蘋果就是倡導 狀態欄 導航欄一體化 所以留個狀態欄 你以為是安卓嗎? 丑爆了 然並卵 開發者只有提建議的權利 沒有決定權 怎么實現 還是要會的 是吧
示例:
- (void)viewDidLoad { [super viewDidLoad]; self.tableView.delegate = self; self.tableView.dataSource = self; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"]; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat offsetY = scrollView.contentOffset.y; if (offsetY > 0) { if (offsetY >= 44) { [self setNavigationBarTransformProgress:1]; } else { [self setNavigationBarTransformProgress:(offsetY / 44)]; } } else { [self setNavigationBarTransformProgress:0]; self.navigationController.navigationBar.backIndicatorImage = [UIImage new]; } } - (void)setNavigationBarTransformProgress:(CGFloat)progress { [self.navigationController.navigationBar lt_setTranslationY:(-44 * progress)]; [self.navigationController.navigationBar lt_setElementsAlpha:(1-progress)]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:YES];//保留狀態欄的那種情況 } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [self.navigationController.navigationBar lt_reset]; }
