iOS-多個UIScrollView滑動巢狀(仿微博、抖音、網易雲個人詳情頁)

QuintGao發表於2019-02-13

前言

最近做專案遇到要實現如微博個人詳情頁的滑動效果,通過查詢資料最終完成了GKPageScrollView,可實現如微博、抖音、網易雲等個人詳情頁的滑動效果。

該庫的實現方式參考了JXPagingView,效果可能更好更全點。

主要功能

  • 支援上下滑動、左右滑動,手勢返回等
  • 支援如UITableView的sectionView的懸停效果
  • 支援多種分頁控制元件,如JXCategory,WMPageController
  • 可實現導航欄顏色漸變、頭圖下拉放大等效果
  • 支援主頁、列表頁下拉重新整理,上拉載入

效果圖

說明 效果圖
微博個人主頁
wb.gif
網易雲歌手頁
wy.gif
抖音個人主頁
dy.gif
主頁下拉重新整理
mainRefresh.gif
列表下拉重新整理
listRefresh.gif

實現

GKPageScrollView的結構為UITableView + tableHeaderView + 分頁控制元件。主要是在UIScrollview的代理方法scrollViewDidScroll方法中做處理,判斷是tableView滑動,還是listView滑動。主要程式碼如下:

// 處理子頁面listScrollView滑動
- (void)listScrollViewDidScroll:(UIScrollView *)scrollView {
    // 如果禁止listScrollview滑動,則固定其位置
    if (!self.isListCanScroll) {
        scrollView.contentOffset = CGPointZero;
    }
    
    // 獲取listScrollview偏移量
    CGFloat offsetY = scrollView.contentOffset.y;
    
    // listScrollView下滑至offsetY小於0,禁止其滑動,讓mainTableView可下滑
    if (offsetY <= 0) {
        self.isMainCanScroll = YES;
        self.isListCanScroll = NO;
        
        scrollView.contentOffset = CGPointZero;
        scrollView.showsVerticalScrollIndicator = NO;
    }else {
        if (self.isListCanScroll) {
            scrollView.showsVerticalScrollIndicator = YES;
        }
    }
}
複製程式碼
// 處理mainTableView滑動
- (void)mainScrollViewDidScroll:(UIScrollView *)scrollView {
    // 獲取mainScrollview偏移量
    CGFloat offsetY = scrollView.contentOffset.y;
    // 臨界點
    CGFloat criticalPoint = [self.mainTableView rectForSection:0].origin.y - self.ceilPointHeight;
    
    // 根據偏移量判斷是否上滑到臨界點
    if (offsetY >= criticalPoint) {
        self.isCriticalPoint = YES;
    }else {
        self.isCriticalPoint = NO;
    }
    
    if (self.isCriticalPoint) {
        // 上滑到臨界點後,固定其位置
        scrollView.contentOffset = CGPointMake(0, criticalPoint);
        self.isMainCanScroll = NO;
        self.isListCanScroll = YES;
    }else {
        if (self.isMainCanScroll) {
            // 未達到臨界點,mainScrollview可滑動,需要重置所有listScrollView的位置
            [[self.delegate listViewsInPageScrollView:self] enumerateObjectsUsingBlock:^(id<GKPageListViewDelegate>  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                UIScrollView *listScrollView = [obj listScrollView];
                listScrollView.contentOffset = CGPointZero;
                listScrollView.showsVerticalScrollIndicator = NO;
            }];
        }else {
            // 未到達臨界點,mainScrollview不可滑動,固定其位置
            scrollView.contentOffset = CGPointMake(0, criticalPoint);
        }
    }
}
複製程式碼

具體是實現還需要看程式碼瞭解

##使用 1、建立GKPageScrollView,並實現其代理方法

// 1、建立GKPageScrollView
self.pageScrollView = [[GKPageScrollView alloc] initWithDelegate:self];
self.pageScrollView.frame = self.view.bounds;
[self.view addSubview:self.pageScrollView];

// 2、實現代理方法
#pragma mark - GKPageScrollViewDelegate
- (UIView *)headerViewInPageScrollView:(GKPageScrollView *)pageScrollView {
    return self.headerView;
}

- (UIView *)pageViewInPageScrollView:(GKPageScrollView *)pageScrollView {
    return self.pageView;
}

- (NSArray<id<GKPageListViewDelegate>> *)listViewsInPageScrollView:(GKPageScrollView *)pageScrollView {
    return self.childVCs;
}
複製程式碼

2、在listView中實現GKPageListViewDelegate代理方法,listView可以是UIView,UIViewController

#pragma mark - GKPageListViewDelegate
- (UIScrollView *)listScrollView {
    return self.tableView;
}

- (void)listViewDidScrollCallback:(void (^)(UIScrollView * _Nonnull))callback {
    self.listScrollViewScrollBlock = callback;
}
複製程式碼

這樣就可實現仿微博個人主頁的效果了。

3、如果想要實現導航欄漸變、頭圖下拉放大效果,需要在下面方法中做處理

- (void)mainTableViewDidScroll:(UIScrollView *)scrollView {
    // 導航欄顯隱
    CGFloat offsetY = scrollView.contentOffset.y;
    // 0-200 0
    // 200 - KDYHeaderHeigh - kNavBarheight 漸變從0-1
    // > KDYHeaderHeigh - kNavBarheight 1
    CGFloat alpha = 0;
    if (offsetY < 200) {
        alpha = 0;
    }else if (offsetY > (kDYHeaderHeight - kNavBarHeight)) {
        alpha = 1;
    }else {
        alpha = (offsetY - 200) / (kDYHeaderHeight - kNavBarHeight - 200);
    }
    self.gk_navBarAlpha = alpha;
    self.titleView.alpha = alpha;
    
    // 頭圖下拉放大  
    [self.headerView scrollViewDidScroll:offsetY];
}
複製程式碼

最後

專案地址:GKPageScrollView

另外推薦下我的圖片瀏覽器GKPhotoBrowser

相關文章