之前通過設置navigationBar的barTintColor設置導航欄顏色航唆,然后拿到self.navigationController.navigationBar.subviews.firstObject對象去修改它的alpha值也可以,但是發(fā)現(xiàn)iOS11出現(xiàn)了問題粪狼,搞了半天也沒很好的解決再榄,但采用設置導航欄的背景圖片再修改背景圖片的alpha來實現(xiàn)導航欄漸變效果是比較容易的享潜。
上滑導航欄漸變顯示剑按,下拉放大頭視圖效果:
隱藏導航欄艺蝴, 改變導航欄背景色,上滑導航欄漸變隱藏效果:
--- ---------------------分割線--- ---------------------
這里先大概扯一下我新建工程的偏好漆诽,不喜可略過:
- MVC
- tabBar - 導航控制器 - 普通VC管理方式
- 采用CocoaPods方式管理第三方庫文件
- 在工程根目錄文件夾下新建兩個文件夾厢拭,BaseFrame(如果想帶公司或個人標識供鸠,比如蘇寧陨闹,可命名為SNBaseFrame)和Modules趋厉。
- 可在Xcode新建New Group, 也可直接工程根目錄showInFinder 創(chuàng)建然后通過Add File to "xx工程",添加進工程中繁堡。
如果采用在finder中新建文件夾再Add File to "xx工程"椭蹄, 需注意:
整個工程文件結構如下:
--- ---------------------分割線--- ---------------------
BaseController作為整個工程所有控制器的父控制器绳矩,自定義導航欄返回按鈕翼馆、取消自動偏移等:
///取消自動偏移
if (!([[UIDevice currentDevice].systemVersion floatValue] >= 11.0)) {
self.automaticallyAdjustsScrollViewInsets = NO;
}
self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = YES;
#pragma mark -lazy load
- (UIButton *)backButton
{
if (!_backButton) {
_backButton= [UIButton buttonWithType:UIButtonTypeCustom];
_backButton.frame = CGRectMake(0, 0, 64, 44);
[_backButton setImage:[UIImage imageNamed:@"navLeft"] forState:UIControlStateNormal];
[_backButton setImage:[UIImage imageNamed:@"navLeft"] forState:UIControlStateHighlighted];
_backButton.imageEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 50);
[_backButton addTarget:self action:@selector(zjsLeftBarButtonItemAction) forControlEvents:UIControlEventTouchUpInside];
}
return _backButton;
}
#pragma mark -左側返回按鈕
- (void)zjsLeftBarButtonItem
{
if (self.navigationController.viewControllers.count > 1) {
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.backButton];
}
}
BaseNavController父導航欄控制器应媚,重寫push方法,定義默認狀態(tài)欄風格祝峻、導航欄title屬性莱找、導航欄背景嗜桌、右滑返回等:
///狀態(tài)欄風格-light
self.navigationBar.barStyle = UIStatusBarStyleLightContent;
///設置導航欄風格
///1. 導航欄背景圖片 - 顏色生成純色圖片
[self.navigationBar setBackgroundImage:[UIImage createImageWithColor:kNavBarColor] forBarMetrics:UIBarMetricsDefault];
///去除導航欄底部橫線
[self.navigationBar setShadowImage:[[UIImage alloc] init]];
//設置導航欄title屬性
[self.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:18], NSForegroundColorAttributeName:[UIColor whiteColor]}];
//側滑返回
self.interactivePopGestureRecognizer.delegate = (id)self;
//重寫系統(tǒng)push方法
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (self.viewControllers.count >= 1) {
viewController.hidesBottomBarWhenPushed = YES;
}
[super pushViewController:viewController animated:animated];
}
BaseTabBarController整個工程的根控制器骨宠,即: window.rootVC, 可控制tabBar顏色层亿,tabBarItem屬性,設置默認tabBarItem等:
self.tabBar.barTintColor = [UIColor whiteColor];
self.tabBar.translucent = NO;//默認YES
[self addViewControllers];
[self setSelectedIndex:0];
#pragma mark -添加子控制器(導航控制器)
- (void)addViewControllers
{
FirstController *firstVC = [[FirstController alloc] init];
BaseNavController *firstNav = [[BaseNavController alloc] initWithRootViewController:firstVC];
SecondController *secondVC = [[SecondController alloc] init];
BaseNavController *secondNav = [[BaseNavController alloc] initWithRootViewController:secondVC];
ThirdController *thirdVC = [[ThirdController alloc] init];
BaseNavController *thirdNav = [[BaseNavController alloc] initWithRootViewController:thirdVC];
FourthController *fourthVC = [[FourthController alloc] init];
BaseNavController *fourthNav = [[BaseNavController alloc] initWithRootViewController:fourthVC];
self.viewControllers = @[firstNav, secondNav, thirdNav, fourthNav];
[self setTabItemIndex:0 withTitle:@"index" withImageName:@"find_normal" withSelectImageName:@"find_selected"];
[self setTabItemIndex:1 withTitle:@"second" withImageName:@"find_normal" withSelectImageName:@"find_selected"];
[self setTabItemIndex:2 withTitle:@"third" withImageName:@"find_normal" withSelectImageName:@"find_selected"];
[self setTabItemIndex:3 withTitle:@"mine" withImageName:@"find_normal" withSelectImageName:@"find_selected"];
}
#pragma mark -自定義item樣式
- (void)setTabItemIndex:(NSInteger)index withTitle:(NSString *)title withImageName:(NSString *)normalImage withSelectImageName:(NSString *)selectImage
{
UITabBarItem *item = [self.tabBar.items objectAtIndex:index];
[item setTitle:title];
/*
typedef struct UIOffset {
CGFloat horizontal, vertical; // specify amount to offset a position, positive for right or down, negative for left or up
} UIOffset;
*/
UIOffset offset;
offset.vertical = -2;//正: 向右或向下 負: 向左或向上
///這里需要兩個值都要配置 否則靜態(tài)分析 報此錯誤
///靜態(tài)分析: Passed-by-value struct argument contains uninitialized data (e.g., field: 'horizontal')
offset.horizontal = 0;
[item setTitlePositionAdjustment:offset];
[item setTitleTextAttributes:@{NSFontAttributeName: Font(11), NSForegroundColorAttributeName: COLOR(@"#999999")} forState:UIControlStateNormal];
[item setTitleTextAttributes:@{NSFontAttributeName: Font(11), NSForegroundColorAttributeName: kNavBarColor} forState:UIControlStateSelected];
UIImage *normalImg = [[UIImage imageNamed:normalImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[item setImage:normalImg];
UIImage *selectImg = [[UIImage imageNamed:selectImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[item setSelectedImage:selectImg];
}
PS: 由于重寫了導航欄碌更,需要自身實現(xiàn)右滑返回,但需要第一個頁面(不能再pop的控制器)的右滑返回響應關閉嘿棘,否則會發(fā)現(xiàn)若你在不能再pop的控制器做了右滑返回操作鸟妙,再點擊按鈕去push操作,發(fā)現(xiàn)界面卡死∧枇樱可pop的控制器打開右滑返回手勢響應脉幢。
網(wǎng)上找到別人的解決方法, 直接拷貝的:
1. 先聲明一個屬性: @property (nonatomic, assign) BOOL isCanUseSideBack;//手勢是否啟動
2. 如下代碼拷貝到第一張控制器頁面:
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self cancelSideBack];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self startSideBack];
}
/**
* 關閉右滑返回
*/
-(void)cancelSideBack{
self.isCanUseSideBack = NO;
if([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;
}
}
/*
開啟右滑返回
*/
- (void)startSideBack {
self.isCanUseSideBack = YES;
if([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = nil;
}
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)gestureRecognizer {
return self.isCanUseSideBack;
}
導航控制器第一個普通控制器關閉右滑返回手勢嫌松,更新: 2017年12月14日
之前說的是一種方式萎羔,但也需要在每個導航控制器的首個普通VC粘貼同樣代碼
如下方式比較簡單:
1. 在導航基類下,遵循協(xié)議<UIGestureRecognizerDelegate, UINavigationControllerDelegate>
2. viewDidLoad中開啟右滑返回手勢:
if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
{
self.interactivePopGestureRecognizer.enabled = YES;
self.interactivePopGestureRecognizer.delegate = self;
self.delegate = self;
}
3. 代理中判斷開啟或關閉右滑返回手勢
#pragma mark -UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer == self.interactivePopGestureRecognizer)
{
if (self.viewControllers.count == 1)
{
return NO;
}
}
return YES;
}
下拉放大tableView的頭視圖效果:
宏定義獲取頭視圖圖片高度:
#define Height_Header SCREEN_Width * 910 / 1200.0
聲明屬性:
@property (nonatomic, strong) UITableView *tableView;
/**
標記當前頁面滑動偏移量
*/
@property (nonatomic, assign) CGFloat contentOffSet_Y;
懶加載tableView:
- (UITableView *)tableView
{
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
_tableView.backgroundColor = kVCViewColor;
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.estimatedRowHeight = 100;
_tableView.rowHeight = UITableViewAutomaticDimension;
_tableView.scrollIndicatorInsets = UIEdgeInsetsMake(StatusBarHeight, 0, 0, 0);
UIView *headView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_Width, Height_Header)];
_tableView.tableHeaderView = headView;
UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_Width, Height_Header)];
img.contentMode = UIViewContentModeScaleAspectFill;
img.image = IMAGE(@"header");
img.tag = 2017;
[headView addSubview:img];
}
return _tableView;
}
將tableView添加到控制器視圖上:
[self.view addSubview:self.tableView];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.and.trailing.equalTo(@0);
make.top.equalTo(self.mas_topLayoutGuideBottom).mas_offset(-kNavBarHeight);
make.bottom.equalTo(self.mas_bottomLayoutGuideTop);
}];
下拉放大頭視圖:
///允許下拉 頭視圖拉伸效果
CGFloat yOffset = scrollView.contentOffset.y;
if (yOffset < 0) {//下拉
//取出圖片視圖
UIImageView *imgView = (UIImageView *)[self.tableView.tableHeaderView viewWithTag:2017];
imgView.frame = CGRectMake(0, yOffset, SCREEN_Width, Height_Header - yOffset);
}
PS:
- 有時產(chǎn)品要求內容全屏顯示,但右側滑動條需要狀態(tài)欄之下
_tableView.scrollIndicatorInsets = UIEdgeInsetsMake(StatusBarHeight, 0, 0, 0);
- tableView的頭視圖添加UIImageView 設置內容模式巷懈,需要設置為UIViewContentModeScaleAspectFill
img.contentMode = UIViewContentModeScaleAspectFill;
/* UIViewContentModeScaleAspectFill, // contents scaled to fill with fixed aspect. some portion of content may be clipped. 部分內容可能被剪裁 */
上滑漸變顯示導航欄:
根據(jù)tableView滑動偏移改變導航欄相關屬性:
#pragma mark -滑動導航漸變
- (void)changeNavBarAlpha:(CGFloat)yOffset
{
CGFloat currentAlpha = (yOffset - (-0))/(Height_Header/2.0 - (-0));
currentAlpha = currentAlpha <= 0.0 ? 0.0 : (currentAlpha >= 1.0 ? 1.0 : currentAlpha);
NSLog(@"---%f", currentAlpha);
[self.navigationController.navigationBar setBackgroundImage:[UIImage createImageWithColor:[UIColor colorWithHexString:kNavBarColorString alpha:currentAlpha]] forBarMetrics:UIBarMetricsDefault];
if (yOffset > Height_Header/2.0) {
self.navigationController.navigationBar.barStyle = UIStatusBarStyleDefault;
[self.backButton setImage:IMAGE(@"navLeft_gray") forState:UIControlStateNormal];
[self.backButton setImage:IMAGE(@"navLeft_gray") forState:UIControlStateHighlighted];
//設置導航欄title屬性
[self.navigationController.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:18], NSForegroundColorAttributeName:[UIColor blackColor]}];
self.title = @"FTest";
} else {
self.navigationController.navigationBar.barStyle = UIStatusBarStyleLightContent;
[self.backButton setImage:IMAGE(@"navLeft") forState:UIControlStateNormal];
[self.backButton setImage:IMAGE(@"navLeft") forState:UIControlStateHighlighted];
//設置導航欄title屬性
[self.navigationController.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:18], NSForegroundColorAttributeName:[UIColor whiteColor]}];
self.title = @"";
}
}
上滑漸變隱藏導航欄:
僅將如下代碼中alpha值 修改為與上滑漸變顯示導航欄相反即可(1 - alpha)
[self.navigationController.navigationBar setBackgroundImage:[UIImage createImageWithColor:[UIColor colorWithHexString:kNavBarColorString alpha:1 - currentAlpha]] forBarMetrics:UIBarMetricsDefault];
另: Appdelegate中適配iOS11(其他簡友總結)
#pragma mark -適配iOS11
- (void)appearanceConfiguration
{
if (@available(iOS 11.0, *)) {
[UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
[UITableView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
[UICollectionView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
[UIWebView appearance].scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
//底下這三句是解決mjrefresh 上拉偏移的bug
[UITableView appearance].estimatedRowHeight = 0;
[UITableView appearance].estimatedSectionHeaderHeight = 0;
[UITableView appearance].estimatedSectionFooterHeight = 0;
} else {
// Fallback on earlier versions
}
}
更新: 2017年12月13日 勾號動畫效果
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self drawSuccessView];
}
return self;
}
- (void)hideSuccessView
{
if (_circleView) {
[_circleView removeFromSuperview];
_circleView = nil;
}
}
- (void)drawSuccessView
{
[self hideSuccessView];
_circleView = [[UIView alloc] initWithFrame:self.bounds];
/**
繪制圓弧
ArcCenter 圓弧中心
radius 半徑
startAngle 開始弧度
endAngle 結束弧度
clockwise 順時針/逆時針
*/
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0) radius:self.frame.size.width/2.0 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
//設置線段兩端樣式
path.lineCapStyle = kCGLineCapRound;
//設置線段連接處的樣式
path.lineJoinStyle = kCGLineCapRound;
//對號第一部分直線的起始
[path moveToPoint:CGPointMake(self.frame.size.width/5.0, self.frame.size.width/2.0)];
CGPoint p1 = CGPointMake(self.frame.size.width/5.0 * 2, self.frame.size.width/4.0 * 3);
[path addLineToPoint:p1];
//對號第二部分起始
CGPoint p2 = CGPointMake(self.frame.size.width/8.0 * 7, self.frame.size.width/3.0);
[path addLineToPoint:p2];
CAShapeLayer *layer = [[CAShapeLayer alloc] init];
//內部填充顏色
layer.fillColor = [UIColor clearColor].CGColor;
//線條顏色
layer.strokeColor = [UIColor orangeColor].CGColor;
//線條寬度
layer.lineWidth = 1;
layer.path = path.CGPath;
//動畫設置
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:NSStringFromSelector(@selector(strokeEnd))];
animation.fromValue = @0;
animation.toValue = @1;
animation.duration = 2;
[layer addAnimation:animation forKey:NSStringFromSelector(@selector(strokeEnd))];
[_circleView.layer addSublayer:layer];
[self addSubview:_circleView];
// ///移除
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [self hideSuccessView];
// });
}
勾號動畫基本參照的這篇文章有些修改了下
實現(xiàn)方式肯定不止一種,可以看下相關
label文字顯示不同顏色與大小:
NSString *string = @"2017南京大屠殺死難者國家公祭儀式";
UILabel *setLabel = [[UILabel alloc] init];
setLabel.text = string;
setLabel.textColor = [UIColor blackColor];
setLabel.font = Font(20);
setLabel.numberOfLines = 0;
[self.view addSubview:setLabel];
[setLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(@15);
make.trailing.equalTo(@-15);
make.top.equalTo(@100);
}];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
NSUInteger firstLoc = [[attributedString string] rangeOfString:@"南"].location;
NSUInteger secondLoc = [[attributedString string] rangeOfString:@"者"].location + 1;
NSRange range = NSMakeRange(firstLoc, secondLoc - firstLoc);
// 改變顏色
[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range];
// 改變字體大小及類型
[attributedString addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica-BoldOblique" size:27] range:range];
// 為label添加Attributed
[setLabel setAttributedText:attributedString];
///直接文字range
NSRange anotherRange = [setLabel.text rangeOfString:@"國家"];
[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor purpleColor] range:anotherRange];
[attributedString addAttribute:NSFontAttributeName value:Font(27) range:anotherRange];
[setLabel setAttributedText:attributedString];