在项目中往往有的时候需要导航栏的状态是变化的,有的时候需要隐藏,为的是显示更多的页面,有的时候需要显示出来,给用户以提示,所以就需要隐藏和显示导航栏。正如下面的示意图所示:
示意图
分析
本个项目中,展示的是一个导航控制器,其中导航控制器中有个UIViewController或者是UITableviewController为根控制器的这么一个结构。
实现
因此在storyboard中我们将之前控制器删除,然后拖一个导航控制器出来,然后试着先绑定一个UITableviewController为根控制器。
导航栏的设置
为了让我们的header view所展示的位置是在左上角的圆点位置,我们需要把自动偏移设置关掉。
self.automaticallyAdjustsScrollViewInsets = NO;
下面就需要隐藏导航栏操作了,我们都知道导航栏有一个隐藏的属性,下面试试
self.navigationController.navigationBar.hidden = YES;
这种方法虽然能够让导航栏消失隐藏掉,但是如果我们要进行滚动tableview的时候,就不能让导航栏渐变的显示出来,所以这种方法不能满足要求。
这种方法行不通那么用透明度的方案来试试:
self.navigationController.navigationBar.alpha = 0;
截图如下:
导航栏没有消失掉
因此上面的方案不能实现功能。
可以使用设置导航栏背景图片进行设置,这样就可以设置导航栏的背景有个透明度的变化。
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
当传入的图片为nil的时候,会自动的创建一个半透明的图片作为导航栏的背景。所以这种方案是可行的,但是导航栏下面的那一根线我们是希望不显示的:
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
这样一来,导航栏的那根线就取消掉了。
以上导航栏的基本实现方案已经确定了,但是下面的列表的显示还有些疑问,到底是用的tableview显示,利用tableview的headerView;还是用UIViewController进行展示头部的控件,下面的部分就用tableview进行展示。
UITableviewController 方案
我们先试着作出示意图的效果,一个tableview上放置一个headerView。
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
header.backgroundColor = [UIColor redColor];
self.tableView.tableHeaderView = header;
运行下,看效果:
tableview header方案看示意图,我们可以看到整个tableview都在移动,而不是我们效果图那种的样式,在往下滚动的时候,头部的控件是不会网下移动的,但是利用tableview的headerView进行布局的方案是不成功的。
UIViewController 方案
我们首先在view上放置一个tableview和UIView(放置头部的那些图片)。
页面的层级以上都是在storyboard中操作的。
UIViewController方案添加header
以上的效果图中可以看到头部的headerView没有类似于tableview的headerView那种滚动的时候出现下移的情况。所以这种方式是可行的。
但是我们还需要设置tableview的偏移量,因为图片的显示,遮挡住了我们的列表,所以需要设置一个偏移量:
self.tableView.contentInset = UIEdgeInsetsMake(244, 0, 0, 0);
导航栏的一些细节处理
导航栏的文字,在刚开始出现的时候是需要隐藏掉的,
//设置标题
UILabel *title = [[UILabel alloc] init];
title.text = @"个人主页";
[title sizeToFit];
// 开始的时候看不见,所以alpha值为0
title.textColor = [UIColor colorWithWhite:0 alpha:0];
self.navigationItem.titleView = title;
虽然我们已经把文字隐藏掉了,但是已进入到控制器,我们还是能看到导航栏,所以我们需要在进入到控制器的时候隐藏掉,就在storyboard中进行设置就可以了,选中控制器:
隐藏导航栏
把top Bar的设置改为None就可以了。
实现滚动隐藏或显示导航栏
我们知道tableview是继承自scrollView的,所以有个-scrollViewDidScroll:
方法中可以拿到tableview的滚动。而且当调用contentInset
会自动调用-scrollViewDidScroll:
。
我们可以这个方法中监听到scrollView的偏移量:
#pragma mark - scrollview
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(@"%f", scrollView.contentOffset.y); // 原始偏移的位置是-244
}
所以导航栏的一些控制操作就在这个方法中进行实现。
我们需要注意到的是,当整个页面上移到一定的位置的时候,就不在上移了,因为需要留够64的位置给导航栏进行显示。也就是说这个显示图片这部分上移到一定的位置就不在移动了。
我们需要改变这个控件的高度,那么就需要修改这个控件高度的约束,所以就需要拖个约束到控制器中。
// 头部展示高度约束
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *imageHeight;
计算头部的高度:
CGFloat offset = scrollView.contentOffset.y - oriOfftY;
CGFloat imgH = oriHeight - offset;
if (imgH < 64) {
// 当上移到距离顶部小于64的时候,就不在移动了。
imgH = 64;
}
self.imageHeight.constant = imgH;
上移、下移
到此我们就需要处理透明度渐变的问题了。
由效果图可以知道,整个页面上移到一定的距离,就会完全显示出导航栏,下移一定的距离,导航栏就会消失掉。
//透明度
//找最大值/
CGFloat alpha = offset * 1 / 136.0; // (200 - 64) / 136.0f
if (alpha >= 1) {
// 透明度最大值
alpha = 0.99;
}
设置文字:
//拿到标题 标题文字的随着移动高度的变化而变化
UILabel *titleL = (UILabel *)self.navigationItem.titleView;
titleL.textColor = [UIColor colorWithWhite:0 alpha:alpha];
最后一步就是修改导航栏的背景的渐变效果:
//把颜色生成图片
UIColor *alphaColor = [UIColor colorWithWhite:1 alpha:alpha];
//把颜色生成图片
UIImage *alphaImage = [UIImage imageWithColor:alphaColor];
//修改导航条背景图片
[self.navigationController.navigationBar setBackgroundImage:alphaImage forBarMetrics:UIBarMetricsDefault];
-imageWithColor :
这个方法是UIImage的一个分类中的方法,专门就是把颜色转换成图片的方法:
// 颜色转为图片
+ (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0, 0, 1.0f, 1.0f);
// 开启位图上下文
UIGraphicsBeginImageContext(rect.size);
// 开启上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
// 使用color演示填充上下文
CGContextSetFillColorWithColor(ref, color.CGColor);
// 渲染上下文
CGContextFillRect(ref, rect);
// 从上下文中获取图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 结束上下文
UIGraphicsEndImageContext();
return image;
}
以上基本完成了想要的效果图的功能了。
代码传送门,如果有帮助你的话,GitHub上给个赞呗!
网友评论