之前通过设置navigationBar的barTintColor设置导航栏颜色,然后拿到self.navigationController.navigationBar.subviews.firstObject对象去修改它的alpha值也可以,但是发现iOS11出现了问题,搞了半天也没很好的解决,但采用设置导航栏的背景图片再修改背景图片的alpha来实现导航栏渐变效果是比较容易的。
上滑导航栏渐变显示,下拉放大头视图效果:
隐藏导航栏, 改变导航栏背景色,上滑导航栏渐变隐藏效果:
--- ---------------------分割线--- ---------------------
这里先大概扯一下我新建工程的偏好,不喜可略过:
- MVC
- tabBar - 导航控制器 - 普通VC管理方式
- 采用CocoaPods方式管理第三方库文件
- 在工程根目录文件夹下新建两个文件夹,BaseFrame(如果想带公司或个人标识,比如苏宁,可命名为SNBaseFrame)和Modules。
- 可在Xcode新建New Group, 也可直接工程根目录showInFinder 创建然后通过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方法,定义默认状态栏风格、导航栏title属性、导航栏背景、右滑返回等:
///状态栏风格-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;
//重写系统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;//正: 向右或向下 负: 向左或向上
///这里需要两个值都要配置 否则静态分析 报此错误
///静态分析: 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: 由于重写了导航栏,需要自身实现右滑返回,但需要第一个页面(不能再pop的控制器)的右滑返回响应关闭,否则会发现若你在不能再pop的控制器做了右滑返回操作,再点击按钮去push操作,发现界面卡死。可pop的控制器打开右滑返回手势响应。
网上找到别人的解决方法, 直接拷贝的:
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. 在导航基类下,遵循协议<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:
- 有时产品要求内容全屏显示,但右侧滑动条需要状态栏之下
_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. 部分内容可能被剪裁 */
上滑渐变显示导航栏:
根据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];
// });
}
勾号动画基本参照的这篇文章有些修改了下
实现方式肯定不止一种,可以看下相关
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];