更新-->
2017.5.25
增加下拉放大的功能, 需要实现headerContentView的frame改变的方法, 如果你是用的Massory或者其他自动布局的方法 就不需要了去实现这个方法了 只要子类的hasHeaderZoom返回YES就可以了
增加是否有导航栏 就是一个值判断headerContentView距离顶部的距离 默认是YES 没有的话 就子类返回NO就可以了
-
当前tableView滚动 自己的通知事件不作任何处理 在通知的userinfo里加了个sender的字段 自己传过去 在通知执行的方法里判断一下就OK了
前言
之前用Reveal简单的分析了一下淘宝的有一些页面, 然后有人让我看一下,简书的个人中心headerView滚动这个视图层级, 当时也是很懵逼, 看不太懂, 这两天有时间, 就仔细去研究了下, 下面是我仿的效果图, 除了头像的缩放之外, 其他的我感觉应该差不多了, 附上demo, 喜欢就给个star, 简单的封装了一下, 可以直接托文件过去用哈
先看效果图
先看简书的个人中心页的视图层级
整个大的页面视图层级还是挺简单的, 满屏的scrollView上, 有3个tableView, 还有一个UISegmentControl来切换3个tableView滚动
他这个头部视图, 是3个列表上都有的, 至于怎么来回切换, 而且上面的显示还是静止的, 我们看一下下面这张图
可以看到, 当滚动的时间, 在scrollView的父控件上多了UIImageView, 而这个imageView上的image, 我猜想就是由列表的头部视图的View生成的一张图片, 生成好之后, 列表的头部视图隐藏, 可以看到文章的那个头部视图已经隐藏了, 然后动态的头部视图还是在的, 只不过是在这个imageView的下面, 当滚动完毕之后, 这个imageView就消失了, 就会出现, 下面滚动, 而上面不滚动的效果, 其实只是遮罩而已, 理解了这个思路, 做起来应该就好做了
下面说说我的做法吧, 大致相似, 有一点不相同的就是头部视图, 我在scrollView的父控件加了headerContentView, 留着放头部视图用的, 下面还有一个导航条, navContentView, 这么做, 无非就是为了自定义, 实例化子类只有, 用什么样的头部视图, 写好之后, 加在headerContentView上就可以了, demo里我已经实例化了一个
直接看代码吧, 里面的传值基本上用的通知, 3个tableView属于同级别的, 想拿到的话, 还得通过父控件, 索性一个通知, 其他监听通知即可
上代码吧:
FMScrollViewController.h
/**
* 初始化方法
*
* @param classes tableView的控制器类名集合
* @param headerViewHeight 头部视图的高度
* @param navViewHeight 导航视图的高度
*
* @return 返回一个实例
*/
- (instancetype)initWithClasses:(NSArray *)classes headerViewHeight:(CGFloat)headerViewHeight navViewHeight:(CGFloat)navViewHeight;
主要看监听的方法吧:
这是scrollView的控制器监听通知的执行的方法, 就是改变头部视图的位置, 以及导航视图的位置
/**
* 监听tableView滚动的通知, 改变头部视图与导航视图的位置
*
* @param noti 将滚动的offset.y值传过来
*/
- (void)_fmscrollSubBaseTableScrollNoti:(NSNotification *)noti{
CGFloat offsetY = [noti.object floatValue];
if (offsetY > self.headerViewHeight) {
offsetY = self.headerViewHeight;
}
CGRect frame = self.headerContentView.frame;
frame.origin.y = - offsetY + 64;
self.headerContentView.frame = frame;
CGRect navFrame = self.navContentView.frame;
navFrame.origin.y = - offsetY + 64 + self.headerViewHeight;
self.navContentView.frame = navFrame;
}
这是同级tableView监听正在滚动tableView的通知执行的方法
/**
* 滚动, 发送通知
*/
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
[[NSNotificationCenter defaultCenter] postNotificationName:FMScrollSubBaseTableScrollNotiKey object:@(scrollView.contentOffset.y)];
}
/**
* 其他列表滚动, 监听通知, 改变y轴的偏移量
*/
- (void)_fmscrollSubBaseTableScrollNoti:(NSNotification *)noti{
CGFloat offsetY = [noti.object floatValue];
if (offsetY < self.headerViewHeight) {
/* 滚动的tableView的头部视图是在屏幕范围内的
此时其他列表的y值偏移量, 与当前滚动的这个列表的偏移量是一样的
*/
self.tableView.contentOffset = CGPointMake(0, offsetY);
} else {
/*
此时头部视图已不再屏幕显示的范围上
需要判断的是, 当前这个列表的偏移, 是不是已经在正好滚动到上面(也就是导航View的下面), 如果是小于这个头部视图的, 要让它滚动到导航视图的下面, 否则不用管,
这里如果不判断的话, 快速滚动, 再去看其他列表, 会出现, 第一个Cell的顶部, 与导航View中间有间距
*/
if (self.tableView.contentOffset.y < self.headerViewHeight) {
self.tableView.contentOffset = CGPointMake(0, self.headerViewHeight);
}
}
}
基本上我的做法还是比较简单的
和简书不同的是, 我这个头部视图在每一个tableView上都是用的tableHeaderView, 简书用的应该是直接加tableView上的一个View, 然后用顶部的内边距, 撑下来的, 这样应该更利于自定义头部视图, 我现在写的就不能再使用tableHeaderView了, 这一点, 后续我会改进, 大致思路的就是这些了
谢谢阅读!!!
再次奉上demo, 效果和我上面那个差不多的 就可以直接使用啦, 有点不同的, 也可以改进改进😋
前言
之前用Reveal简单的分析了一下淘宝的有一些页面, 然后有人让我看一下,简书的个人中心headerView滚动这个视图层级, 当时也是很懵逼, 看不太懂, 这两天有时间, 就仔细去研究了下, 下面是我仿的效果图, 除了头像的缩放之外, 其他的我感觉应该差不多了, 附上demo, 喜欢就给个star, 简单的封装了一下, 可以直接托文件过去用哈
先看效果图
先看简书的个人中心页的视图层级
整个大的页面视图层级还是挺简单的, 满屏的scrollView上, 有3个tableView, 还有一个UISegmentControl来切换3个tableView滚动
他这个头部视图, 是3个列表上都有的, 至于怎么来回切换, 而且上面的显示还是静止的, 我们看一下下面这张图
可以看到, 当滚动的时间, 在scrollView的父控件上多了UIImageView, 而这个imageView上的image, 我猜想就是由列表的头部视图的View生成的一张图片, 生成好之后, 列表的头部视图隐藏, 可以看到文章的那个头部视图已经隐藏了, 然后动态的头部视图还是在的, 只不过是在这个imageView的下面, 当滚动完毕之后, 这个imageView就消失了, 就会出现, 下面滚动, 而上面不滚动的效果, 其实只是遮罩而已, 理解了这个思路, 做起来应该就好做了
下面说说我的做法吧, 大致相似, 有一点不相同的就是头部视图, 我在scrollView的父控件加了headerContentView, 留着放头部视图用的, 下面还有一个导航条, navContentView, 这么做, 无非就是为了自定义, 实例化子类只有, 用什么样的头部视图, 写好之后, 加在headerContentView上就可以了, demo里我已经实例化了一个
直接看代码吧, 里面的传值基本上用的通知, 3个tableView属于同级别的, 想拿到的话, 还得通过父控件, 索性一个通知, 其他监听通知即可
上代码吧:
FMScrollViewController.h
/**
* 初始化方法
*
* @param classes tableView的控制器类名集合
* @param headerViewHeight 头部视图的高度
* @param navViewHeight 导航视图的高度
*
* @return 返回一个实例
*/
- (instancetype)initWithClasses:(NSArray *)classes headerViewHeight:(CGFloat)headerViewHeight navViewHeight:(CGFloat)navViewHeight;
主要看监听的方法吧:
这是scrollView的控制器监听通知的执行的方法, 就是改变头部视图的位置, 以及导航视图的位置
/**
* 监听tableView滚动的通知, 改变头部视图与导航视图的位置
*
* @param noti 将滚动的offset.y值传过来
*/
- (void)_fmscrollSubBaseTableScrollNoti:(NSNotification *)noti{
CGFloat offsetY = [noti.object floatValue];
if (offsetY > self.headerViewHeight) {
offsetY = self.headerViewHeight;
}
CGRect frame = self.headerContentView.frame;
frame.origin.y = - offsetY + 64;
self.headerContentView.frame = frame;
CGRect navFrame = self.navContentView.frame;
navFrame.origin.y = - offsetY + 64 + self.headerViewHeight;
self.navContentView.frame = navFrame;
}
这是同级tableView监听正在滚动tableView的通知执行的方法
/**
* 滚动, 发送通知
*/
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
[[NSNotificationCenter defaultCenter] postNotificationName:FMScrollSubBaseTableScrollNotiKey object:@(scrollView.contentOffset.y)];
}
/**
* 其他列表滚动, 监听通知, 改变y轴的偏移量
*/
- (void)_fmscrollSubBaseTableScrollNoti:(NSNotification *)noti{
CGFloat offsetY = [noti.object floatValue];
if (offsetY < self.headerViewHeight) {
/* 滚动的tableView的头部视图是在屏幕范围内的
此时其他列表的y值偏移量, 与当前滚动的这个列表的偏移量是一样的
*/
self.tableView.contentOffset = CGPointMake(0, offsetY);
} else {
/*
此时头部视图已不再屏幕显示的范围上
需要判断的是, 当前这个列表的偏移, 是不是已经在正好滚动到上面(也就是导航View的下面), 如果是小于这个头部视图的, 要让它滚动到导航视图的下面, 否则不用管,
这里如果不判断的话, 快速滚动, 再去看其他列表, 会出现, 第一个Cell的顶部, 与导航View中间有间距
*/
if (self.tableView.contentOffset.y < self.headerViewHeight) {
self.tableView.contentOffset = CGPointMake(0, self.headerViewHeight);
}
}
}
基本上我的做法还是比较简单的
和简书不同的是, 我这个头部视图在每一个tableView上都是用的tableHeaderView, 简书用的应该是直接加tableView上的一个View, 然后用顶部的内边距, 撑下来的, 这样应该更利于自定义头部视图, 我现在写的就不能再使用tableHeaderView了, 这一点, 后续我会改进, 大致思路的就是这些了
谢谢阅读!!!
再次奉上demo, 效果和我上面那个差不多的 就可以直接使用啦, 有点不同的, 也可以改进改进😋