UITableView的嵌套+左右侧滑选项卡的头部悬停

PS:也是看别人写的。自己刚好有这个需求,看了代码,改吧改吧就用了。找不到那篇文章了。

效果:实现tableview的嵌套,页面可以左右滑动切换页面。头部轮播图隐藏的时候,选项卡实现头部悬停的效果。如下:


UITableView的嵌套+左右侧滑选项卡的头部悬停_第1张图片
滑动效果.gif

分析过程:
1.看到可以上下滑动,并带有头view,立马想到是最外层是UITableView
2.三个按钮的选项卡可以悬停到头部,立马想到是sectionHeader,tableview用plain样式。更加确定是最外层用tableview做的。
3.可以滑动,这种样式是scrollview或者collectionview上添加tableview

所以,层级关系是tableview-->collectionview-->tableview

开始也想着根据偏移量,打开或者关闭用户交互,设置偏移量啥的,试了试,发现效果太差,后来上网搜了,找了别人的方法,看着代码,自己试了试,能达到我需要的效果。自己看明白了,就挪到自己项目里了。

其实全篇看下来,主要是通过一个全局的BOOL值,设置tableview是否需要滑动,在scrollview的代理方法里,根据tableview的偏移量,再结合这个BOOL值,判断是否需要滑动,同时设置tableview的偏移量。

一、最外层tableview

1.上下滑动的tableview

由于屏幕上有多个tableview,需要同时相应操作,所以这个tableview需要接受多个手势。需要新建一个tableview,继承自UITableView,遵守手势代理,运行接受多个手势。暂时称为大tableview,有个canScroll属性。
h文件

#import 

@interface MainTableView : UITableView 

@end

m文件

#import "MainTableView.h"

@implementation MainTableView

//允许接受多个手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    
    return YES;
}

@end

还需要headView,sectionHeaderView等。

2.横向滑动的collectionview

由于最外层的tableview只起到上下滑动的作用,所以一个cell就够了。
cell的高度 = 屏幕高度 - 头view高度 - sectionHeader高度。
在这个cell上添加一个collectionview,横向滑动,collectionview大小和cell大小一致。
紧接着在这个collectionview上添加几个tableview,这几个tableview大小和collectionview大小一致,即和最外层唯一的大cell的大小一致。暂时称为小tableview.也有个canScroll属性。
添加小tableview的时候,用了addChildViewController方法,等于先添加子控制器,用了子控制器的tableview。

    self.subVC1 = [[SubTableVC alloc] init];
    [self addChildViewController:self.subVC1];
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"UICollectionViewCellID" forIndexPath:indexPath];
    cell.backgroundColor = [UIColor yellowColor];
    
    SubTableVC *subVC = self.childViewControllers[indexPath.row];
    subVC.view.frame = CGRectMake(0, 0, SCREENW, SCREENH-64-49-40);
    subVC.tableView.frame = CGRectMake(0, 0, SCREENW, SCREENH-64-49-40);
    [cell.contentView addSubview:subVC.view];
    return cell;
}

这样就完成了整体的结构。

三、监听tableview的偏移量

直接根据scollview的代理方法,- (void)scrollViewDidScroll:(UIScrollView *)scrollView;监听大tableview的滑动。

这里是重点。慢慢滑动页面,慢慢体会。

大tableview的滑动:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    if (scrollView == self.tableView) {
     
        CGFloat scrollY = [self.tableView rectForSection:0].origin.y;
        
        if (scrollView.contentOffset.y >= scrollY) {
            
            if (self.canScroll == YES) {
                
                self.canScroll = NO;
                
                self.subVC1.canScroll = YES;
                self.subVC1.tableView.contentOffset = CGPointZero;
                self.subVC2.canScroll = YES;
                self.subVC2.tableView.contentOffset = CGPointZero;
                self.subVC3.canScroll = YES;
                self.subVC3.tableView.contentOffset = CGPointZero;
            }
            
            self.tableView.contentOffset = CGPointMake(0, scrollY);
            
        }else{
            //这句判断,是在小tableview往滑动的时候,需要固定大tableview的偏移量,原因参考第6点。
            if (self.canScroll == NO) {
                self.tableView.contentOffset = CGPointMake(0, scrollY);
            }
        }
    }
}

过程分析:
1.根据实际需求,首次加载页面的时候,大tableview需要滑动,小tableview不需要滑动,这个时候是大tableview带着小tableview跑。所以大tableview的canScroll=YES,小tableview的canScroll=NO。两者的属性值一直是相反的。实际情况也只这样 ,滑动的时候,只需要一个滑动就够了。

2.等滑动头view消失的时候,大tableview就不需要滑动,小tableview滑动。
(scrollY是头tableview中第一个section的Y坐标。也就是头view需要消失的时候的偏移量)。

3.第一次向下滑动,从大tableview下滑动开始,直到头view消失之前,这个时间段这个代理方法不需要啥操作,这段时间是大tableview带着小tableview滑动。

4.等第一次滑动偏移量=scrollY的时候,,这个时候大tableview就不需要滑动了,该小tableview滑动了。所以这时候需要if (scrollView.contentOffset.y >= scrollY)这个判断开始起作用。

5.继续往下滑,都是小tableview在滑动了。看起来貌似没大tableview的事情了。接着就网上滑动了,需要回去了。

6.重点:虽然canScroll属性=NO,但不代表大小tableview不会滑动了,它每时每刻都在响应着scrollview的代理方法。它还会滑动,只是我们不让它滑动,不需要滑动的时候,我们就固定它的偏移量。(这点很重要)

小tableview滑动的监听
block是为了通知大tableview可以滑动了。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    if (self.canScroll == NO) {
        scrollView.contentOffset = CGPointZero;
    }
    
    if (scrollView.contentOffset.y < 0 ) {
        self.canScroll = NO;
        scrollView.contentOffset = CGPointZero;
        self.block();
    }
}

7.页面初始化canScroll=NO,所以为了不让它滑动,就设置偏移量=0,等到可以滑动的时候,canScroll=YES。

8.该往上滑回到顶部了。第6点说过,tableview一直响应滑动的方法,所以一直网上滑,当scrollView.contentOffset.y < 0,说明小tableview到顶部了,就不需要它滑动了,设置canScroll=NO,通知大tableview可以滑动了。

9.在block通知中设置大tableview canScroll=YES,回到了初始状态,完成了整个过程。
demo

你可能感兴趣的:(UITableView的嵌套+左右侧滑选项卡的头部悬停)