iOS仿微博发现页实现

某一天接到一个需求,要求做一个类似微博发现页的页面,需要支持上下滑动的同时可以左右滑动展示更多的内容,就像下图这样

WX20190617-135231.png

蓝框下方的部分可以左右滑动,蓝框以及蓝框上边的部分不可以左右滑,点击蓝框中的title蓝框下方会切换不同的页面,左右滑蓝框下方的页面蓝框里的title也会实时变化为高亮,往上滑的时候蓝框内的部分会吸顶

大致的实现方法是用一个大的TableView实现,这个页面大概可以分为三部分


WX20190617-135136.png
  • 第一部分是固定的,其实就是tableView的HeadView
  • 第二部分(暂且叫做categoryView) 其实是tableView的第一个section的headerView,内部有一个点击切换的效果
  • 第三部分是tableView的一个Cell,Cell内部是一个UICollectionView,可以左右滑动,滑动时与categoryView联动,collectionView的每一个cell是一个TableView,在categoryView吸顶的时候可以自由滑动

难题一:当视图滑动一部分之后,手指在第三部分滑动的时候,会触发第三部分视图内的某个TableView的滑动,这时候外部的大的tableView就会失去滑动效果,想要滑动只能是滑动第三部分上方的视图。

解决方案:将最外部的tableView变成新建的一个tableView类,(继承自UITableView)然后将它的- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer方法重写

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];
}

这样可以保证你在滑动第三部分里的小的tableView时,外部的大的tableView依然可以滑动,但这时候这两种滑动会重叠,也就是说你滑动第三部分的tableView时,大的tableView也在滑动,我们要的效果是无论何时只有一个tableView在滑动,所以我们要实时监测这两个tableView的偏移量,当一个tableView滑动的时候让另一个tableView的contentOffset始终为0,造成一种不动的错觉,分两种情况:

  • 第二部分没有吸顶的时候,保持外部的大tableView滑动效果,小tableView虽然也可以滑动,但是要造成它不动的效果
  • 第二部分吸顶的时候,只让小的tableView滑动,外部的大tableView要造成不动的效果

同时检测这两个tableView的代理方法- (void)scrollViewDidScroll:(UIScrollView *)scrollView,针对大的TableView:

    if (self.currentScrollingListView != nil && self.currentScrollingListView.contentOffset.y > 0) {
        //mainTableView的header已经滚动不见,开始滚动某一个listView,那么固定mainTableView的contentOffset,让其不动
        self.mainTableView.contentOffset = CGPointMake(0, [self.delegate tableHeaderViewHeightInPagerView:self]);
    }

    if (scrollView.contentOffset.y < [self.delegate tableHeaderViewHeightInPagerView:self]) {
        //mainTableView已经显示了header,listView的contentOffset需要重置
        NSArray *listViews = [self.delegate listViewsInPagerView:self];
        for (UIView <JXPagerViewListViewDelegate>* listView in listViews) {
            [listView listScrollView].contentOffset = CGPointZero;
        }
    }

针对小的tableView

    if (self.mainTableView.contentOffset.y < [self.delegate tableHeaderViewHeightInPagerView:self]) {
        //mainTableView的header还没有消失,让listScrollView一直为0
        scrollView.contentOffset = CGPointZero;
        scrollView.showsVerticalScrollIndicator = NO;
    }else {
        //mainTableView的header刚好消失,固定mainTableView的位置,显示listScrollView的滚动条
        self.mainTableView.contentOffset = CGPointMake(0, [self.delegate tableHeaderViewHeightInPagerView:self]);
        scrollView.showsVerticalScrollIndicator = YES;
    }

这样就可以实现一种自动吸顶同时又比较顺滑的滑动效果

难题二: categoryView与第三部分多个View的联动效果

categoryView的实现方式是用一个collectionView实现的,下方第三部分也是一个collectionView, 在封装第二部分视图的时候,里边有一个UIScrollview类型的属性,将第三部分的collectionView赋给这个属性,然后通过KVO监听第三部分collectionView的滑动,就可以将第二部分的collectionView的cell的点击事件和第三个collectionView的滑动关联起来

[contentScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"contentOffset"] && (self.contentScrollView.isTracking || self.contentScrollView.isDecelerating)) {
        //用户滚动引起的contentOffset变化,才处理。
        CGPoint contentOffset = [change[NSKeyValueChangeNewKey] CGPointValue];
        [self contentOffsetOfContentScrollViewDidChanged:contentOffset];
    }
}

这里只是记录了大体的思路,来理解这个效果是怎样实现的,其实还有很多需要注意的细节,源代码是两个第三方JXCategoryViewJXPagingView

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,135评论 1 32
  • ----“求真悟道”2019全国小学数学教育论坛归来 2019年6月2日-3日参加了由《教育研究与评论》和《教育视...
    华琴_5c0e阅读 1,154评论 0 0
  • 为了日更,每晚写到十一二点。 昨晚发布一篇,看了一下时间11:48分,自我感觉还拿得出手,于是找了几个专题投稿,投...
    清风雪1阅读 1,020评论 10 7
  • 2018.8.21号星期二晴三一班麻永卓妈妈 由于下雨的原因,两天了都没有来水,这个时候才知道水是多么的重...
    a爱英阅读 218评论 0 2
  • 雨是一把神秘的钥匙,开启了山 我与春天一同步入山中 海在天上,繁星追逐群山 野蔷薇是群山卷起的浪花 时光微微香,因...
    大小周阅读 953评论 18 24