iOS開發筆記13:頂部標籤式導航欄及下拉分類菜單

    當內容及分類較多時,每每採用頂部標籤式導航欄,例如網易新聞客戶端的頂部分類導航,最近恰好有這樣的應用場景,參考網絡上一些demo,實現了這種導航效果,記錄一些要點。git

    效果圖(因爲視頻轉GIF掉幀,滑動和下拉動畫顯得比較生硬,剛發現quickTime能夠直接錄製手機視頻,推薦一下,很方便)github

    

     1.頂部標籤式導航欄

   (1)實現思路

      其實就是在上下兩個UIScrollView上作文章,實現聯動選擇切換的效果。網絡

     ①頂部標籤導航欄topCategoryListScrollView加載顯示分類數據,下方contentScrollView顯示分類對應的內容,選擇頂部標籤後,內容視圖contentScrollView切換到對應視圖。一樣,滑動下方內容視圖,標籤欄滑動到指定分類並居中顯示,若分類初始位置在導航欄最左側或最右側,則不用滑動到中間位置。以避免兩側留出一段空白。動畫

    ②頂部導航欄能夠用label或button來表明分類,這裏用的是label,添加了一個tap手勢響應交互事件,將分類抽取爲一個model,包含分類名稱、對應內容視圖特有的id或url及分類名稱長度(分類下方的下劃線長度隨名稱長度變化)等屬性,根據分類的多少,決定下方內容視圖的contentSize,再將分類順序與內容順序對應起來,在交互邏輯中實現聯動切換。ui

    ③點擊右側按鈕,彈出下拉菜單,也可切換分類。url

   (2)iOS7上Autolayout的問題

    因爲iOS7的Autolayout與iOS八、9的差別,在iOS7上UIScrollView的contentsize及一些使用Autolayout的UIView動畫效果很差處理,因此這裏使用setFrame的方式來實現兩個頂部導航欄及下拉菜單的UI效果。spa

   (3)頂部導航欄

     遍歷分類數據,往頂部導航欄添加label。須要注意如下幾點:3d

    ①設置label的tag,與分類數據的index對應,方便後續根據標識進行切換選擇;code

    ②label的userInteractionEnabled默認爲NO,須要設置一下,方便響應tap點擊操做;視頻

    ③分類名稱長度是動態的,若是超出默認長度則根據實際長度顯示,包括label的長度及label底部下劃線長度,因此分類數據對應的model裏須要有一個長度屬性,用來記錄此長度,方便後續顯示,而不用實時去計算長度。   

     分類名稱底部的下劃線隨着分類label走,默認選中第一個label,因此下劃線默認也是停留在第一個,而且根據分類數量設置好頂部導航欄的contentSize。

   (4)內容視圖

     一樣根據分類數量設置好內容視圖的contentSize

       

   (5)兩個scrollView之間的交互邏輯 

     兩個scrollView之間的聯動須要注意單向傳遞,避免發生重複滑動。這裏的滑動選擇操做就三種狀況:

    ①選擇某個分類標籤,導航欄滑動到指定位置,內容視圖滑動到指定位置;

    ②滑動內容視圖,導航欄也切換滑動到對應分類標籤位置;

    ③在下拉菜單中選擇了某個分類,導航欄和內容視圖滑動到對應位置,實際與①同樣。

    這裏先說第一種狀況,點擊導航欄的分類標籤,則block回調到controller裏

      先讓contentScrollView滑動到指定位置,再通知topCategoryListScrollView滑動。

      這裏須要說明一下,scrollViewDidEndScrollingAnimation本來是內容視圖滑動結束後調用,用來通知導航欄滑動到對應分類標籤。scrollViewDidEndDecelerating是處理手指在屏幕上滑動內容視圖結束後調用,也是通知導航欄滑動到對應分類標籤。可是爲了讓滑動時分類標籤切換顯示效果更連貫,在scrollViewDidScroll裏進行了處理,當滑出必定距離,新的index與當前index不一致時就通知導航欄切換分類標籤,實際上scrollViewDidEndScrollingAnimation和scrollViewDidEndDecelerating這時已經能夠去掉了。

    相似的,第二種狀況,滑動內容視圖,導航欄切換滑動到對應分類標籤位置,實際就是在ScrollViewDidScroll中進行判斷處理的。

    對於第三種狀況,下拉菜單中選擇分類,實際過程與第一種狀況同樣。

    須要注意的是切換分類時,須要記錄更新當前分類的值,彈出下拉菜單的時候,才能標識高亮當前分類。

    導航欄滑動的時候,須要針對分類標籤的具體位置,決定是否滑動,以及滑動距離,並根據分類名稱長度更新下劃線的長度

      可是這裏還忽略了一種狀況,當分類標籤顯示不足一屏時,offsetMax爲負值,點擊某個分類,會將全部分類總體往右移動,很是怪異,這種狀況下,點擊分類就不須要滾動了。

     2.下拉分類菜單

   (1)使用場景及方式

     下拉逐漸展開分類菜單,選擇某一個分類,導航欄和內容視圖切換到對應分類及內容,展開狀態時,點擊按鈕或者背景陰影區域逐漸收起菜單。

   (2)UI元素分解

      一個放在導航欄旁邊的按鈕dropDownButton,一個titleView(其實titleView放在下拉菜單裏更合適,這樣就不須要單獨處理它),以及下拉分類菜單dropDownCategoryListView,裏面包含一個collectionView展現分類數據。dropDownButton控制titleView及dropDownCategoryListView的顯示,dropDownCategoryListView背景色設置必定透明度作背景。接下來總結一下幾個關鍵點。

   (3)collectionView高度控制及分隔線效果

     這裏每一行顯示三個分類數據,分類數量及cell高度肯定後便可肯定collectionView的高度,即先肯定縱向有幾行分類數據,行數 x cell高度就是collectionView 高度。

     這裏還須要注意一點,默認設置collectionView是不可滑動的,可是須要判斷一下分類顯示的高度,超出可視範圍時,須要容許滑動。

     對於分類cell的分隔線效果,可能最容易想到的就是cell之間留出間隙,collectionView背景色設置一下就好了,可是這裏有兩個問題,首先是三等分cell加上留出的間隙,間隙的寬度會帶有小數,顯示出來的效果粗細不均,而且這裏cell與collectionview背景色都爲白色,留出空隙也沒法造成分隔線的視覺效果,因此只能在cell內部處理,底部和右側加分隔線,根據cell所處位置控制分隔線顯示與否。

   (4)點擊collectionView的事件處理

      dropDownCategoryListView 添加了tap手勢,點擊view則通知controller收起移除下拉分類菜單 ,collectionView做爲一部分,點擊collectionView也會通知controller收起移除下拉分類菜單,顯然不符合要求,解決辦法是將手勢的cancelsTouchesInView屬性設爲NO,即將touch事件也傳遞到collectionView上,didSelect選中分類後繼續處理便可。

   (5)交互效果處理

     下拉菜單的展開和收起漸變效果用UIView的animation便可,須要注意的是收起動畫效果,須要先去掉陰影,而後收起下拉菜單,這裏的陰影其實就是dropDownCategoryListView設置了必定透明度的背景色,因此先將背景色設成clearColor再收起菜單便可。

     3.參考

     (1)http://code.cocoachina.com/view/128556

     (2)https://github.com/dsxNiubility/SXNews

相關文章
相關標籤/搜索