效果如下:
首先看到这个效果,第一反应就是使用
tableview
的头部控件来实现,类似如下代码:
//返回每一组的头部视图
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
//在这⾥里设置组的头部视图是位置和宽⾼高都是没有效果的, 它专⻔门有⼀一个⽅方法来设置头部 视图的⾼高度
UIView *sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
sectionHeader.backgroundColor = [UIColor yellowColor];
return sectionHeader;
}
分析:因为示例效果的头部视图在滚动的时候一直是在上部0的位置,而且往下滚动时,会用放大的效果,但是这在个地方,如果使用的是TablView
的的头部视图,tableView
的头部视图默认是跟着一起滚动的,而且手动去设置HeaderView
的y值是没有效果的,所以使用头部视图是不可行的。
方案:使用UIViewcontrller
,添加tableview
,上部的效果使用UIView+ImageView
来实现,图片的拉升效果设置UIImageView
的contentModel
属性即可实现。
首先达到导航条隐藏的效果,第一反应就是设置导航条的透明度,设置导航条透明度为0,但是没有效果,还是原来的样⼦。
因为导航条上面那一块并不直接是导航条,它是导航条里面的⼀个子控件,所以在这里设置它没有效果,因为系统会生成⼀个半透明的图片。
self.navigationController.navigationBar.alpha = 0.0;
所以在这里可以考虑给它设置一个半透明的图片,有一个模式,必须要传默认UIBarMetricsDefault
模式, 图片设为nil
的时候,也没有效果,那是因为系统它做了⼀层判断,它会判断如果传入的图片为空的话,它就会帮你生成一个半透明的图片,设置导航条的背景图片。
[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
同时,导航条标题文字也是需要开始隐藏,随着tableview
向上滚动才会显现出来:
// 设置导航条文字
UILabel *titleL = [[UILabel alloc] init];
titleL.text = @"个人详情页";
[titleL sizeToFit];
// 设置颜色和透明度:0-0:黑色透明,1-1:白色不透明
titleL.textColor = [UIColor colorWithWhite:0 alpha:0];
self.navigationItem.titleView = titleL;
导航条隐藏效果实现了,现在就可以开始实现滚动向上走的效果了,如何实时的获取tableview
滚动的位置?监听代理,实现代理方法,根据tableview
的实时滚动位置,来求出整个HeaderView
的显示高度,就可以达到一边,滚动HeaderView
一边向上走的效果。实现代码如下:
// 已经在滚动了
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// 获取scrollview的当前偏移量
CGPoint offset = scrollView.contentOffset;
//当前Y方向的偏移量-初始偏移量=Y的偏移高度
CGFloat offsetY = offset.y - FLOriOffsetY;
// headerView的实时高度
CGFloat constant = FLHeaderH - offsetY;
NSLog(@"scrollH:%f,%f",offsetY,offset.y);
// 实时高度小于64时,确定为64,导航条留出显示位置
if (constant < 64) {
constant = 64;
offsetY = 136;
}
self.headVHeigthConstrain.constant = constant;
// 透明度
CGFloat alpha = offsetY / (FLHeaderH - 64);
NSLog(@"scrollH:%f,%f",offsetY,alpha);
// 系统如果发现传入透明度为1的背景图片,会生成一张半透明的图片替换,
// 把透明度设置成0.99可以避免这个问题
if (alpha == 1) {
alpha = 0.99;
}
// 根据颜色生成一张相同颜色图片,并设置透明度
UIImage *image = [UIImage imageWithColor:[UIColor colorWithWhite:1 alpha:alpha]];
[self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
// 设置titleView文字显示
UILabel *titleL = (UILabel *)self.navigationItem.titleView;
titleL.textColor = [UIColor colorWithWhite:0 alpha:alpha];
}
如果你得到的效果如下:
是因为图片显示效果超出了控件的范围,只需要把超出的部分裁剪掉即可,在SB中勾选图片的
clip to Bounds
属性:clip to Bounds属性
这里还是用到了UIImage的一个分类,根据颜色自动生成一张1*1图片:
+ (UIImage *)imageWithColor:(UIColor *)color
{
// 描述矩形
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
// 开启位图上下文
UIGraphicsBeginImageContext(rect.size);
// 获取位图上下文
CGContextRef context = UIGraphicsGetCurrentContext();
// 使用color演示填充上下文
CGContextSetFillColorWithColor(context, [color CGColor]);
// 渲染上下文
CGContextFillRect(context, rect);
// 从上下文中获取图片
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
// 结束上下文
UIGraphicsEndImageContext();
return theImage;
}
完整代码如下:
#import "FLPersionDetailVC.h"
#import "UIImage+Image.h"
//头部View的⾼高度
#define FLHeaderH 200
//悬浮条的⾼高度
#define FLTarBarH 44
///原始的便宜量.
#define FLOriOffsetY -244
@interface FLPersionDetailVC () <UITableViewDataSource, UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *headVHeigthConstrain;
@property (weak, nonatomic) IBOutlet UIImageView *iconImageV;
@end
@implementation FLPersionDetailVC
static NSString *cellID = @"cellID";
- (void)viewDidLoad {
[super viewDidLoad];
// 注册cell
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellID];
//iOS7之后,只要是导航控制器下的所有UIScrollView顶部都会添加额外的滚动区域. 设置当前控制器不要调整ScrollView的contentInsets
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
self.tableView.contentInset = UIEdgeInsetsMake(FLHeaderH+FLTarBarH, 0, 0, 0);
NSLog(@"contentInset:%@", NSStringFromUIEdgeInsets(self.tableView.contentInset));
/*
设置导航条透明度为0,没有效果,还是原来的样⼦. 原因是因为导航条上面那一块并不直接是导航条,它是导航条里面的⼀个子控件. 所以在这里设置它没有效果,因为系统会生成⼀个半透明的图片.
self.navigationController.navigationBar.alpha = 0.0;
所以在这里我们可以考虑给它设置一个半透明的图片. 在这里,有一个模式,必须要传默认UIBarMetricsDefault模式. 在这里发现设为nil的时候,也没有效果,那是因为系统它做了⼀层判断,它会判断如果传入的系统图片为空的话,它就会帮你生成一个半透明的图片,设置导航条的背景图片.
**/
[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
// 设置导航条文字
UILabel *titleL = [[UILabel alloc] init];
titleL.text = @"个人详情页";
[titleL sizeToFit];
// 设置颜色和透明度:0-0:黑色透明,1-1:白色不透明
titleL.textColor = [UIColor colorWithWhite:0 alpha:0];
self.navigationItem.titleView = titleL;
// 个人头像圆形显示
self.iconImageV.layer.cornerRadius = self.iconImageV.frame.size.width *0.5;
self.iconImageV.layer.masksToBounds = YES;
}
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
cell.textLabel.text = @"个人详情";
return cell;
}
// 已经在滚动了
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// 获取scrollview的当前偏移量
CGPoint offset = scrollView.contentOffset;
//当前Y方向的偏移量-初始偏移量=Y的偏移高度
CGFloat offsetY = offset.y - FLOriOffsetY;
// headerView的实时高度
CGFloat constant = FLHeaderH - offsetY;
NSLog(@"scrollH:%f,%f",offsetY,offset.y);
// 实时高度小于64时,确定为64,导航条留出显示位置
if (constant < 64) {
constant = 64;
offsetY = 136;
}
self.headVHeigthConstrain.constant = constant;
// 透明度
CGFloat alpha = offsetY / (FLHeaderH - 64);
NSLog(@"scrollH:%f,%f",offsetY,alpha);
// 系统如果发现传入透明度为1的背景图片,会生成一张半透明的图片替换,
// 把透明度设置成0.99可以避免这个问题
if (alpha == 1) {
alpha = 0.99;
}
// 根据颜色生成一张相同颜色图片,并设置透明度
UIImage *image = [UIImage imageWithColor:[UIColor colorWithWhite:1 alpha:alpha]];
[self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
// 设置titleView文字显示
UILabel *titleL = (UILabel *)self.navigationItem.titleView;
titleL.textColor = [UIColor colorWithWhite:0 alpha:alpha];
}
@end
网友评论