iOS仿微博发现页实现

2019-06-17  本文已影响0人  左左4143

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

WX20190617-135231.png

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

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


WX20190617-135136.png

难题一:当视图滑动一部分之后,手指在第三部分滑动的时候,会触发第三部分视图内的某个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的代理方法- (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

上一篇 下一篇

猜你喜欢

热点阅读