** 测试环境 : **Xcode8.1 iOS10.1
现在看到好多应用都有类似上面滑动悬停的效果,我之前也写过类似的,现在新项目又有这种效果,之前写得也有点乱,所以就趁这次重写的机会把写这种效果的思路再重新整理一遍。当然我只是为实现这种效果提供一种比较笨的思路,如果大家有更好更简单的思路可以留言。
实现思路挺简单,但是写起来挺麻烦的,先看层级图:
UI层级图.png
- 设置主内容View(backView)
- 首先在控制器view上面添加一个scrollowView,它是用来左右滑动以显示不现的内容tableView
- 再在scrollowView上面添加多个(按自己需求)tableView,从左到右依次布局这些tableView,并设置每个tableView的tableHeadView(此处设置tableHeadView只是用来占位用,没有显示的作用)(注意:所有tableView的headView的高度一定要相同)
// scrollView
UIScrollView* scrollView = [[UIScrollView alloc] init];
[self.view addSubview:scrollView];
scrollView.backgroundColor = [UIColor whiteColor];
self.scrollView = scrollView;
scrollView.pagingEnabled = YES;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.delegate = self;
scrollView.contentSize = CGSizeMake(kScreenWidth * 3, 0);
[scrollView makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
UIView* headView = [[UIView alloc] init];
headView.frame = CGRectMake(0, 0, 0, self.headViewHeight + TitleHeight);
self.tableViewHeadView = headView;
headView.backgroundColor = [UIColor greenColor];
CFContentTableView* table1 = [[CFContentTableView alloc] init];
table1.delegate = self;
self.table1 = table1;
table1.tableHeaderView = headView;
[scrollView addSubview:table1];
[table1 makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(scrollView);
make.width.equalTo(kScreenWidth);
make.top.equalTo(self.view);
make.bottom.equalTo(self.view);
}];
CFContentTableView* table2 = [[CFContentTableView alloc] init];
table2.delegate = self;
self.table2 = table2;
table2.tableHeaderView = headView;
[scrollView addSubview:table2];
[table2 makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(scrollView).offset(kScreenWidth);
make.width.equalTo(table1);
make.top.bottom.equalTo(table1);
}];
CFContentTableView* table3 = [[CFContentTableView alloc] init];
table3.delegate = self;
self.table3 = table3;
table3.tableHeaderView = headView;
[scrollView addSubview:table3];
[table3 makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(scrollView).offset(kScreenWidth*2);
make.width.equalTo(table1);
make.top.bottom.equalTo(table1);
}];
- 设置头部View(headView)
- 创建需要悬停的headView(非tableHeadView),headView包含悬停view,并把headView添加到控制器View上面,使其正好覆盖在tableHeadView上。
- 监听tableView的滑动位置(contentOffset),并根据滑动位置去设置headView的frame,还要设置其它tableView的contentOffset,判断如果tableView滑动将要使悬停View超出目标悬停位置时则固定住悬停view。
- (void)setupHeadView
{
UIView* headBackView = [[UIView alloc] init];
headBackView.backgroundColor = [UIColor blueColor];
headBackView.frame = CGRectMake(0, 0, kScreenWidth, self.headViewHeight + TitleHeight);
[self.view addSubview:headBackView];
self.headBackView = headBackView;
CFTitleBar* titleBarView = [[CFTitleBar alloc] init];
[headBackView addSubview:titleBarView];
self.titleBarView = titleBarView;
titleBarView.backgroundColor = [UIColor whiteColor];
[titleBarView makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(headBackView);
make.bottom.equalTo(headBackView.mas_bottom);
make.height.equalTo(TitleHeight);
}];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView == self.scrollView || !scrollView.window)
{
return;
}
CGFloat offsetY = scrollView.contentOffset.y;
CGFloat originY = 0;
CGFloat otherOffsetY = 0;
if (offsetY <= self.headViewHeight)
{
originY = -offsetY;
if (offsetY < 0)
{
otherOffsetY = 0;
}else{
otherOffsetY = offsetY;
}
}else{
originY = -self.headViewHeight;
otherOffsetY = self.headViewHeight;
}
self.headBackView.frame = CGRectMake(0, originY, kScreenWidth, self.headViewHeight+TitleHeight);
for ( int i = 0; i<self.titleBarView.titles.count; i++ )
{
if (i != self.titleBarView.selectedIndex)
{
UITableView* contentView = self.scrollView.subviews[i];
CGPoint offset = CGPointMake(0, otherOffsetY);
if ([contentView isKindOfClass:[UITableView class]])
{
if (contentView.contentOffset.y < self.headViewHeight || offset.y < self.headViewHeight)
{
[contentView setContentOffset:offset animated:NO];
}
}
}
}
}
以上就是整体的思路,看起来也不难但是�写起来有些麻烦,如果再加上实际应用中的各种逻辑就会更乱一些,而且对于界面跳转会有很多问题,我也在陆续填坑,如果大家在开发这种效果时遇到了坑欢迎留言一起探讨。
更新(2016年10月11日)
昨天看了简书的个人页面,感觉做得更好一些,关键是它的headView部分也可以接收滑动,而我之前做的由于headView挡住了tableView导致无法接受滑动。经过昨天半天的各种尝试目前的实现基本和简书效果一致,headView也可以滑动了。
具体实现自己看代码吧,虽然实现起来挺简单的,但是寻找这种解决方法还是费了不少时间。
最后奉上demo地址
网友评论
问题:我用了collectionView 然后在切换btn点击之后,collectionView的头部显示出来了,但是,我一拉collectionView 又闪的一下消失了