類似貼吧,簡書等個人內(nèi)容比較豐富的APP,個人頁面除了彰顯個性,內(nèi)容的展示也非常重要,現(xiàn)在普遍的設(shè)計都是頂部個人信息和統(tǒng)計,下半部分則是個人內(nèi)容的展示。例如我的簡書個人主頁:

這里包含幾個特別有意思的功能:
- 頂部導(dǎo)航欄背景隱藏
- 上拉逐漸顯示導(dǎo)航欄
- 下拉背景圖片放大
- 上拉背景視圖向上滾動,在內(nèi)容切換的視圖置頂(導(dǎo)航欄下面)之后,背景視圖停止?jié)L動,內(nèi)容則可以繼續(xù)滾動。
- 內(nèi)容可以由內(nèi)容切換視圖內(nèi)部的按鈕進(jìn)行切換
總體來說,這是一個經(jīng)典的ScrollView的嵌套案例,Github已經(jīng)有類似的方案提供了,大家可以參考:
JXPagingView
這個是我最近在Github上看到的,star數(shù)非常多,而且作者也寫了原理,并一直在進(jìn)行維護(hù),推薦使用。
HJTabViewController
我的APP用的都是這個,目前來看還不錯,不過好久沒有維護(hù)了。
所以這次決定就研究下HJTabViewController的實現(xiàn)原理,看看自己有沒有實力寫一個類似的庫。
圖層結(jié)構(gòu)
先來談下圖層結(jié)構(gòu),這是一個典型的ScrollView的嵌套結(jié)構(gòu),即一個橫向滾動的ScrollView嵌套一個縱向滾動的ScrollView。
而HeaderView,TabView,則是位于ScrollView之上,利用ScrollView的Insets來進(jìn)行設(shè)計。

- 紅色為UIPageView
- 藍(lán)色的UIScrollView,他被添加到UIPageView中,負(fù)責(zé)橫向滾動,因此pagingEnabled設(shè)置為YES
- 白色的UIScrollView,來自INSPageContentViewController的UIScrollView,以Page的形式添加到UIScrollView中,負(fù)責(zé)垂直滾動。
- 粉色的是UIStackView,包含了一個HeaderView和一個TabView,注意,他是被添加到UIPageView中的
利用UIScrollView的Insets
白色的UIScrollView,他的Insets.top被設(shè)定為UIStackView的高度,默認(rèn)情況下,白色UIScrollView的初始的ContentOffset為(0, -insets.top),同時UIStackView的Y坐標(biāo)的位置為0,此時看上去就會是頂部是UIStackView,接下來就是白色UIScrollView的內(nèi)容。
垂直滾動時,我們唯一需要處理的就是UIStackView的Y坐標(biāo)的位置(或者UIStackView的高度)。
水平滾動時,我們需要處理Page頁面的切換,和TabView指示器的切換。
最終的代碼在這里:
INSPageView
大家可以結(jié)合源碼和Demo進(jìn)行理解。