前言:
时间轴如下:
1 .首先看一遍实现效果还有源码,源码这里下载:https://github.com/Ade0408/PersonDetailPage
2 .花一个早上的时间实现还有各个细节点分析
3 .差不多一个下午的时间写总结
4.本文仅仅供个人学习记录
效果如下:
- 拖动效果:
- 向上滑动时,HeadView会跟着向上滑动,并且滑动到选项卡的区域时,就不会再向上滑动
- 向下滑动时,HeadView的高度会随着拉动而变大,实现放大背景图的效果
思路如下:
- 1 . 搭建界面布局,设置好约束(注意 : HeadView 和 选项卡都是直接添加到主View上的,并不是在TableView上)
- 2 . HeadView 背景图注意点:需要设置背景图片的内容模式为
UIViewContentModeScaleAspectFill(内容填充)
,只有设置成这个才能随着HeadView的变大而变大,但是还有需要注意的是,同时我们还需要设置把图片多出来的部分给剪切掉,因为UIViewContentModeScaleAspectFill(内容填充)
是同比例变大,所以会有多出的部分,可以通过设置imageV的clipsToBounds
属性为YES
- 3 . 设置一些常量属性:
- HeadView 高度
- HeadView 最小高度 (当等于这个最小高度时,状态栏才会完全显示出来)
- 选项卡高度
- 原始偏移量 : - (HeadView 高度 + 选项卡高度),注意:该常量是负的,该原始偏移量就是tableView的 contentOffset.y
- 4 . 接下来可以开始写代码了,我们目前需要做4件事:
- 4.1 把导航栏完全隐藏
- 4.2 把导航栏上的文字隐藏
- 4.3 把tableView的内容下移244个单位(HeadView 高度+选项卡高度)
- 4.4 让底下的tableView不要自动滚动64个单位
- (void) setNavgationBarHide {
/** 把tableview视图整体往下移动244个单位,因为这一部分是头部视图还有选项卡的大小 */
// kHeaderViewHeight 和 kChooseViewHeight 都是前面说到的常量,一个是200,一个是44
self.contentTableView.contentInset = UIEdgeInsetsMake(kHeaderViewHeight+kChooseViewHeight,0, 0, 0);
/** 不要自动往下滚动64个单位.(64是原本状态栏还有导航栏的高度合) */
self.automaticallyAdjustsScrollViewInsets = NO;
/** 设置导航栏为透明,其原理就是传入一个没有图片,但又不为空的UIImage给导航栏 */
[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc]init] forBarMetrics:UIBarMetricsDefault];
/** 把导航栏上的分隔线用一个没有图片,但又不为空的UIImage给覆盖掉 */
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
/** 添加自定义title */
UILabel *contentLable = [[UILabel alloc] init];
contentLable.text = @"微博个人详情页面";
/** 让label根据文字的大小自己调整大小 */
[contentLable sizeToFit];
self.navigationItem.titleView = contentLable;
/** 默认隐藏title */
contentLable.textColor = [UIColor colorWithWhite:0 alpha:0];
/** 让控制器的self.contentLabel指向contentLable,这样方便我们后续对它进行操作 */
self.contentLabel = contentLable;
}
- 5 . 这时你可以先给tableView设置一些假数据,使它等会可以拖动到底部
- 6 . 使用 UIScrollView 的代理方法 (
scrollViewDidScroll:
) 监听滚动事件 - 7 . 这是最重要的一步,总体效果都在这里进行实现,虽然都是在 UIScrollView 代理方法里进行实现,但是还是分开来写.这里我们需要把它拆分成几个步骤来做:
- 7.1 计算偏移量,这个偏移量的计算公式为:用户滚动视图的偏移量 - 原始偏移量,也就是如下公式:
/** 计算偏移量,originalOffset也就是上面提到的原始偏移量,因为我们把tableView往下移动了244个单位,所以这个原始偏移量就是这个值 */
CGFloat offset = scrollView.contentOffset.y - originalOffset;
- 7.2 计算偏移高度
// 偏移高度 = 默认高度 - 偏移量
CGFloat offsetHeight = kHeaderViewHeight - offset;
- 7.3 设置headView 的高度随着下拉或上拉而变化 (注意点 : HeadView的最小高度是64,我们在前面已经设置过这个常量了,那么当偏移高度小于这个值时,我们默认设置为这个值,并且通过设置这个值,我们还可以实现选项卡悬停效果) :
/** 悬停效果,其实就是不让图片的高度继续减小,最小只能是64 */
if (offsetHeight < kHeaderViewMinHeight) {
offsetHeight = kHeaderViewMinHeight;
}
/** 通过修改Height达到效果,当向上滚动时,选项卡向上滚动的速度比头部视图的还要快一点 */
self.headViewHeightConstraint.constant = offsetHeight;
效果如图:
- 7.4 程序写到这里,其实大部分效果都实现了,但是还差一个导航栏和导航栏上的文字随着向上拉动而逐渐显示,实现代码如下:
// alpha 值计算 : 偏移量 / (headView默认高度 - headView最小高度) ,当大于1时,导航栏和contentLabel就会完全显示
CGFloat alpha = offset / (kHeaderViewHeight - kHeaderViewMinHeight);
// 前面我们设置好的 contentLabel ,可以在这里去动态设置它的alpha值
self.contentLabel.textColor = [UIColor colorWithWhite:0 alpha:alpha];
// 这里直接使用袁峥的Category方法,返回一张通过传入颜色,返回一张1*1的图片,navigationBar会图片拉伸填充到整个导航栏
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor colorWithWhite:1 alpha:alpha]] forBarMetrics:UIBarMetricsDefault];
结语:
若大家在观看本文的过程发现我有任何的理解错误,可以在本文下进行评论,我会第一时间进行修改,最后,谢谢您的阅读!
我的源码地址:https://github.com/Ade0408/PersonDetailPage