方法一
[self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self.navigationBar setShadowImage:[self imageWithColor:[UIColor redColor] size:CGSizeMake([UIScreen mainScreen].bounds.size.width, 0.5)]];
#pragma mark - public methods
- (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size {
if (!color || size.width <= 0 || size.height <= 0) return nil;
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
此方法是現(xiàn)在大部分博客中有介紹的,不過有缺陷。如果
self.navigationBar.translucent = YES;
則navigationbar
透明了挡篓。有時我們又不得不設(shè)self.navigationBar.translucent = YES;
例如使用UISearchController
做通訊錄時。其中的坑可以看我這篇博文介紹使用UISearchController時 navigationBar translucent 屬性導(dǎo)致的問題總結(jié)。
方法二
此方法是我推薦的一種庄蹋,詳情請看代碼及代碼注釋。(不過在iOS11+后不能使用迷雪,需要使用方法三)
首先導(dǎo)入頭文件
#import <objc/runtime.h>
代碼展示
//先查看View層次結(jié)構(gòu)
NSLog(@"Navigationbar recursiveDescription:\n%@",[self.navigationBar performSelector:@selector(recursiveDescription)]);
//打印完后我們發(fā)現(xiàn)有個高度為0.5的UIImageView 類型 SuperView type為 _UIBarBackground的視圖
//遍歷navigationBar 屬性
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList([self.navigationBar class], &outCount);
for (NSInteger i = 0; i < outCount; ++i) {
Ivar ivar = *(ivars + i);
NSLog(@"navigationBar Propertys:\n name = %s \n type = %s", ivar_getName(ivar),ivar_getTypeEncoding(ivar));
}
free(ivars);
//遍歷結(jié)果可以發(fā)現(xiàn)navigationbar 中的type 為_UIBarBackground 名稱為 _barBackgroundView
//遍歷_barBackgroundView 中的屬性
unsigned int viewOutCount = 0;
UIView *barBackgroundView = nil;
/*iOS 10.0+為`_barBackgroundView`,小于iOS10.0這個屬性名稱為`_UIBarBackground`.*/
if (sysytemVersion<10.0) {
barBackgroundView = [self.navigationBar valueForKey:@"_backgroundView"];
}else{
barBackgroundView = [self.navigationBar valueForKey:@"_barBackgroundView"];
}
if (barBackgroundView) {
Ivar *viewivars = class_copyIvarList([barBackgroundView class], &viewOutCount);
for (NSInteger i = 0; i < viewOutCount; ++i) {
Ivar ivar = *(viewivars + i);
NSLog(@"_barBackgroundView Propertys:\n name = %s \n type = %s", ivar_getName(ivar),ivar_getTypeEncoding(ivar));
}
free(viewivars);
}
//找到type為 UIImageView 的屬性有_shadowView,_backgroundImageView限书。因為底部線條可以設(shè)置shadowImage,所有我們猜測是_shadowView
UIImageView *navigationbarLineView = [barBackgroundView valueForKey:@"_shadowView"];
if (navigationbarLineView && [navigationbarLineView isKindOfClass:[UIImageView class]]) {
UIView *lineView = [[UIView alloc]init];
lineView.backgroundColor = [UIColor redColor];
lineView.translatesAutoresizingMaskIntoConstraints = NO;
[navigationbarLineView addSubview:lineView];
//這里我們要用約束不然旋轉(zhuǎn)后有問題
[navigationbarLineView addConstraint:[NSLayoutConstraint constraintWithItem:lineView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:navigationbarLineView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
[navigationbarLineView addConstraint:[NSLayoutConstraint constraintWithItem:lineView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:navigationbarLineView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
[navigationbarLineView addConstraint:[NSLayoutConstraint constraintWithItem:lineView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:navigationbarLineView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]];
[navigationbarLineView addConstraint:[NSLayoutConstraint constraintWithItem:lineView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:navigationbarLineView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0]];
}
為了更好的理解,我加了分析過程章咧,實際應(yīng)用時倦西,可以去掉分析過程。
方法三
UIView *lineView = [[UIView alloc]init];
lineView.backgroundColor = [UIColor redColor];
lineView.translatesAutoresizingMaskIntoConstraints = NO;
[self.navigationBar addSubview:lineView];
UIView *superView = self.navigationBar;
[superView addConstraint:[NSLayoutConstraint constraintWithItem:lineView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:superView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
[superView addConstraint:[NSLayoutConstraint constraintWithItem:lineView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:superView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]];
[superView addConstraint:[NSLayoutConstraint constraintWithItem:lineView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:superView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0]];
[lineView addConstraint:[NSLayoutConstraint constraintWithItem:lineView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:1]];
下載鏈接
擴展
方法二中你可以寫個category
添加和移除