仿 Unread 實(shí)現(xiàn)位于屏幕底部的優(yōu)雅導(dǎo)航欄

TL;DR

源代碼 GitHub 地址:https://github.com/caiyue1993/Tiptoes

前言

靈感最初來(lái)源于 Unread 的 iOS 客戶端。

Unread 首頁(yè)
Unread 首頁(yè)

當(dāng)我第一次打開(kāi)這個(gè)應(yīng)用時(shí),我就被它的 UI 深深吸引了:和大多數(shù)國(guó)內(nèi) app 使用泛濫的 TNV (TabBarController -> NavigationController -> ViewController) 架構(gòu)不同, Unread 它沒(méi)有使用 UITabBarController 也沒(méi)有使用系統(tǒng)自帶的 UINavigationController,界面沒(méi)有任何無(wú)關(guān)內(nèi)容,讓用戶沉浸在應(yīng)用中,享受應(yīng)用提供的內(nèi)容信息流,這種體驗(yàn)簡(jiǎn)直完美。

它的交互也幾乎都是通過(guò)手勢(shì)操作:下拉刷新,右滑(屏幕任何位置)返回,另外左滑和上提同樣會(huì)觸發(fā)相應(yīng)動(dòng)作。在小屏幕上可能感受不到這種便利,但是在稍微大些的屏幕上如果非要通過(guò)點(diǎn)擊左上角的返回鍵才能返回的話,那真的是一件十分痛苦的事情。

Unread 位于底部的導(dǎo)航欄也很有意思,我以為這也是一種很大的創(chuàng)新,它擯棄了系統(tǒng)自帶的 navigation bar,將導(dǎo)航欄移到屏幕的最下方,交互同樣絲般順滑,讓人贊不絕口。

所以,我就想模仿著實(shí)現(xiàn)這樣一個(gè)導(dǎo)航欄。

思路

當(dāng)時(shí)立馬腦海里想到的有三種大致的思路:

第一種,嘗試是否能直接更改系統(tǒng) navigation bar 的位置,將其移至屏幕下方,并設(shè)置合理的大小和想要的外形。

第二種,自己實(shí)現(xiàn)一個(gè) NavigationController:里面放置一個(gè) UIScrollView,將棧上的 view controller 都放入其中,然后配置一個(gè)自定義導(dǎo)航欄,根據(jù) UIScrollView 的 contentOffset 來(lái)實(shí)現(xiàn)過(guò)渡效果。

第三種,直接繼承系統(tǒng)的 UINavigationController 并進(jìn)行私人定制,滿足我們的需要。

篩選最優(yōu)解

針對(duì)第一種思路,翻看官方的 UINavigationController 的文檔,里面寫(xiě)了這樣一句話:

The navigation controller manages the creation, configuration, and display of the navigation bar and optional navigation toolbar. It is permissible to customize the navigation bar’s appearance-related properties but you must never change its frame, bounds, or alpha values directly.

因此拋棄思路一。

第二種思路,很明顯實(shí)現(xiàn)這種思路工作量較大,我們既然有了系統(tǒng)提供的 UINavigationController,為什么不在它提供的接口上進(jìn)行些許的 tweak ,進(jìn)而滿足我們的需求呢?(其實(shí)在 GitHub 上已經(jīng)有人用第二種方法實(shí)現(xiàn)了,有興趣的讀者可以搜搜)

所以最終我選擇了短平快的第三種思路:對(duì)系統(tǒng)自帶導(dǎo)航控制器進(jìn)行定制,實(shí)現(xiàn)需求。

相關(guān)知識(shí)

關(guān)于 UINavigationController:

navigation controller
navigation controller

一個(gè) navigation controller 它自己會(huì)維護(hù)一個(gè) viewControllers 的數(shù)組,另外,navigation controller 有一個(gè)屬性 view ,該 view 中包含了 navigation bar,toolbar(可選),另外還有一個(gè) content view。在視圖的前進(jìn)以及后退中,只有 content view 是一直在變的(等于 viewControllers 最上面的 view controller 的 view),而 navigation bar 以及 toolbar(可選) 只有內(nèi)容會(huì)變(例如標(biāo)題),而它們本身作為視圖是不變的。

關(guān)于 UINavigationItem:

每個(gè)被壓入 navigation stack 中的 view controller 都必須有 UINavigationItem ,用來(lái)展示在 NavigationBar 上面。而 navigation controller 會(huì)根據(jù) stack 最上面的兩個(gè) view controller 生成 navigation bar 的內(nèi)容。

關(guān)于 UINavigationBar, 看官方文檔中的一句話:

A navigation bar is most commonly used within a navigation controller. The UINavigationController object creates, displays, and manages its associated navigation bar, and uses attributes of the view controllers you add to control the content displayed in the navigation bar.

另外,我們可以通過(guò) UINavigationBarDelegate 獲取當(dāng)前需要管理的 UINavigationItem,然后即可獲取 UINavigationItem 的 title 等信息,展示在 NavigationBar 上。

如何實(shí)現(xiàn)右滑返回時(shí)的過(guò)渡效果

首先,加上了兩個(gè) UILabel: currentTitleLabel 和 priorTitleLabel,分別用來(lái)記錄當(dāng)前 view controller 的標(biāo)題以及前一個(gè) view controller 的標(biāo)題。
另外,由于 UINavigationController 有一個(gè) UIGestureRecognizer 屬性,可以用來(lái)追蹤右滑的手勢(shì),從而可以拿到在當(dāng)前視圖上的偏移量,進(jìn)而可以實(shí)現(xiàn)自定義的過(guò)渡效果。
還有,UINavigationBarDelegate 提供了四個(gè)代理方法 (shouldPush,didPush,shouldPop,didPop),可以通過(guò)這樣的四個(gè)節(jié)點(diǎn)來(lái)配置 currentTitleLabel 和 priorTitleLabel 的始末節(jié)點(diǎn)時(shí)的狀態(tài)。

目前的效果是這樣的:

![](fade in and out)

之后要做的

  • 實(shí)現(xiàn)更多的過(guò)渡效果
  • 找到更好的解決中途取消右滑返回的方案(現(xiàn)在采用的是一種 work around,具體可以看源代碼 TiptoesNavController.swift 中的 handleTiptoesDisplay(sender:) 方法)

個(gè)人精力有限,希望可以發(fā)揮開(kāi)源社區(qū)的力量吧,最后再貼一下源代碼地址:https://github.com/caiyue1993/Tiptoes。

如果你單純喜歡本項(xiàng)目的想法,可以 ?Star 支持;如果你對(duì)項(xiàng)目代碼有更好的建議,可以直接提 issue 或者 pull request。謝謝:)

參考資料

關(guān)注我


本文原地址:http://soledad.me/2017/01/18/about-tiptoes/

本文版權(quán)所有,如需轉(zhuǎn)載,請(qǐng)告知原作者并注明出處

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容