UIScrollView嵌套滾動完美解決方案:仿淘寶、轉轉首頁

前言

隨著APP承載的業(yè)務越來越多,一個頁面顯示的信息也越來越多,需要為不同的業(yè)務導流。主流的平臺APP,諸如:淘寶、京東、轉轉、盒馬、還有各類社交APP的個人主頁,都需要在頁面頂部展示核心業(yè)務數(shù)據(jù),在底部分標簽顯示各個子業(yè)務列表數(shù)據(jù)。隨著大屏手機的普及,如果只能通過點擊頂部標簽切換列表,對于使用場景最高的單手操作就很麻煩了。所以,為了用戶更好的交互,需要支持子列表左右滾動切換的功能。這樣就出現(xiàn)了UIScrollView嵌套滾動的場景了。既需要主列表上下滾動,也需要子列表左右滾動。

現(xiàn)有的解決方案

為了解決嵌套滾動的問題,現(xiàn)在網(wǎng)上已經(jīng)有許多解決方案了。包括筆者我,也開源了一個JXPagingView庫,目前已經(jīng)有1100 stars,得到許多朋友的認可。
主要支持以下特性:

  • 列表懶加載
  • 主列表、子列表下拉刷新
  • 懸浮位置調(diào)整
  • OC與Swift雙版本
  • 封裝度高,使用方便

感興趣的可以了解一下JXPagingView的原理

基于現(xiàn)有的原理,有一個小問題:當用戶在頂部header用力往上滑動的時候,當分類控制器滾動到頂部的時候,會突然停住,列表不會接著慣性繼續(xù)滾動。大家可以打開【京東】APP,目前(版本號:8.3.4)首頁的效果就是如此,大家可以體驗一下,就明白我說的是什么意思了。

如何才能像淘寶首頁那樣,可以讓子列表接著滾動呢?直到看到了轉轉首頁,通過上手體驗之后,發(fā)現(xiàn)了一個全新的方案。PS:不知道轉轉APP做了什么操作,簡單的逆向不起作用,視圖層級都看不到。所以,這個方案都是靠自己猜測加實踐折騰出來的。

JXPagerSmoothView方案

JXPagerSmoothView Github地址,點擊立馬體驗

效果預覽

image

可以清楚的看到頂部pagerHeader用力往上滾動之后,下方列表會繼續(xù)滾動的,而且滾動的速度、阻尼都是系統(tǒng)自帶的。因為上下滾動的時候,就只是在操作一個列表,自然不會有手勢沖突之類的問題,看了下面的原理解析就明白了。自定義的pagerHeader只是用一個簡單的TableView作為示例,你可以用任何復雜的視圖、UICollectionView等代替。

此方案原理非常簡單,沒有復雜的手勢處理,只需要處理好各種邊界情況即可。

情況一

默認情況pagerHeaderContainerView被addSubview到當前的列表UIScrollView上面,pagerHeaderContainerView就是頂部pagerheader(核心業(yè)務視圖區(qū)域)和pinHeader(懸浮分類控制器區(qū)域)的容器視圖。這樣子,列表上下滑動就只是在操作單個列表ScrollView,不會有滾動突然被中斷的情況。視圖層級如下:

image

情況二

當列表在左右切換的時候、列表向上滾動到pinHeder懸浮的時候,pagerHeaderContainerView被addSubview到JXPagerSmoothView上面,也就是脫離了列表scrollView,達到固定在頂部的效果。視圖層級如下:

image

總結:就是在不斷切換pagerHeaderContainerView的父視圖,達到淘寶、轉轉首頁的效果。是不是原理很簡單?當然使用的代碼也很簡單!

使用示例

1、初始化JXPagerSmoothView

    self.pager = [[JXPagerSmoothView alloc] initWithDataSource:self];
    [self.view addSubview:self.pager];

2、初始化pagerHeaderpinHeader

    self.categoryView = [[JXCategoryTitleView alloc] init];
    self.categoryView.titles = @[@"能力", @"愛好", @"隊友"];
    self.categoryView.contentScrollViewClickTransitionAnimationEnabled = NO;

    self.pagerHeader = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"lufei.jpg"]];

3、實現(xiàn)JXPagerSmoothViewDataSource代理方法

- (CGFloat)heightForPagerHeaderInPagerView:(JXPagerSmoothView *)pagerView {
    return 300;
}

- (UIView *)viewForPagerHeaderInPagerView:(JXPagerSmoothView *)pagerView {
    return self.pagerHeader;
}

- (CGFloat)heightForPinHeaderInPagerView:(JXPagerSmoothView *)pagerView {
    return 50;
}

- (UIView *)viewForPinHeaderInPagerView:(JXPagerSmoothView *)pagerView {
    return self.categoryView;
}

- (NSInteger)numberOfListsInPagerView:(JXPagerSmoothView *)pagerView {
    return self.categoryView.titles.count;
}

- (id<JXPagerSmoothViewListViewDelegate>)pagerView:(JXPagerSmoothView *)pagerView initListAtIndex:(NSInteger)index {
    SmoothListViewController *listVC = [[SmoothListViewController alloc] init];
    return listVC;
}

4、列表實現(xiàn)JXPagerSmoothViewListViewDelegate代理方法

SmoothListViewController類實現(xiàn)JXPagerSmoothViewListViewDelegate代理方法

- (UIScrollView *)listScrollView {
    return self.tableView;
}

- (UIView *)listView {
    return self.view;
}

使用注意事項

通過示例代碼可以看到整個邏輯簡單、清晰,和使用UITableView一樣,只需要實現(xiàn)對應的代理方法即可,根本不需要操心頁面的交互邏輯。真正的做到了高內(nèi)聚低耦合、職責分離等原則。

但是有幾個點需要注意:

  • 不要自己設置列表滾動視圖的contentInset屬性,內(nèi)部通過設置contentInset來添加pagerHeaderContainerView;
  • 當頂部pagerHeader是一個UIScrollView及其子類時,需要讓contentSize.height=pagerHeader的高度,即不能讓其能夠滾動,詳情可以參考OC示例demo的SmoothCustomPagerHeaderViewController類;
  • 請仔細辨別JXPagerViewJXPagerSmoothView的區(qū)別,并選擇適合自己需求的類;
  • JXPagerSmoothView在1.2.1及以上版本才有,請使用最新版本;
  • Swift版本是JXPagingSmoothView;

JXPagerSmoothView Github地址

JXPagerSmoothView Github地址,點擊立馬體驗

總結

JXPagerSmoothView的實現(xiàn)文件只有300行代碼左右,需要深入研究的朋友,相信花點功夫就能看懂。這樣子以后業(yè)務上面有任何特殊要求時,都可以自己實現(xiàn)。只要掌握了原理,就不怕需求的變化。

有任何建議或疑問,可以留言、提Issues,我都會第一時間回復你!

感謝你的閱讀,喜歡就點個贊吧??

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • 簡書編輯器目測不支持html的一些語法,導致部分圖片顯示有問題,對于圖片又最大只支持5M,建議前往原文地址或者是掘...
    Jiar_閱讀 3,948評論 2 2
  • 你是誰 你在尋找誰 你在扮演誰 你在逃避誰 你獨自一人躲進了寒夜 所有的火焰被撕成白雪 你無力地掬著雪花 想點燃它...
    季夢VC_ETG閱讀 285評論 0 4
  • 社交是一個廣義的概念,就互聯(lián)網(wǎng)產(chǎn)品開發(fā)而言,社交app的開發(fā)思路已經(jīng)明顯從社交通訊功能,轉向社交表達功能。一方面,...
    冬瓜西瓜閱讀 308評論 0 0
  • 每個人的人生,都是一場獨特的旅行,前方未知,也許藏著精彩無限,這一生,你遇見誰錯過誰,都不重要,重要的是,你是否能...
    安心悅舍閱讀 338評論 3 2
  • HTML5定義了一些新的標記規(guī)則,也定義了一些新的JavaScript API,能夠讓開發(fā)人員創(chuàng)建出更好的用戶界面...
    jluemmmm閱讀 206評論 0 0