導航欄顏色、透明度漸變

前言

在開發過程中,經常會碰到控制器對應的導航欄的背景顏色不一致或者需要讓導航欄背景透明的需求。在導航控制器push和pop視圖控制器的過程中,直接修改導航欄背景色在視覺上會顯得比較突兀。為了給用戶更好的使用體驗,就需要為導航欄的背景色和透明度變換添加一種合適的動畫效果。

UINavigationBar基礎

概述

導航欄是UINavigationBar類的實例對象,是一個顯示在窗口的頂部并包含用于在屏幕層次結構內進行導航的按鈕的柵欄。導航欄最常用于導航控制器中,導航控制器對象創建、顯示和管理導航欄,并使用導航控制器管理的視圖控制器的相關屬性來控制導航欄中顯示的內容。

圖2-1

使用導航控制器控制導航欄時,需要執行以下步驟:

  • Interface Builder或代碼中創建一個導航控制器。
  • 使用UINavigationController對象的navigationBar屬性配置導航欄的外觀。
  • 通過設置導航控制器堆棧中管理的每個視圖控制器的titlenavigationItem屬性來控制導航欄的內容。

也可以單獨使用導航欄,將導航欄添加到界面中時需要執行以下步驟:

  • 設置自動布局規則來管理界面中導航欄的位置。
  • 創建一個root navigationItem來提供初始標題。
  • 配置委托對象來處理與導航欄的交互。
  • 自定義導航欄的外觀。
  • 配置應用程序界面,以便用戶在瀏覽分層屏幕時推入和彈出相關navigationItem

導航欄和導航控制器配合使用

使用導航控制器來管理不同內容屏幕之間的導航時,導航控制器會自動創建導航欄,并在適當的時間推入和彈出navigationItem

在視圖控制器出棧和入棧時,導航控制器使用此視圖控制器對象的navigationItem屬性為其導航欄提供當前需要顯示的內容。默認的navigationItem使用視圖控制器的標題,但可以通過覆蓋UIViewController子類的navigationItem屬性來完全控制導航欄內容。

導航控制器會自動將其自身指定為其導航欄對象的委托對象,所以在使用導航控制器時,不要將導航欄的委托對象設置為自定義對象。

要訪問與導航控制器關聯的導航欄,請使用UINavigationController對象的navigationBar屬性。

有關導航控制器的信息,可以參看UINavigationController

添加視圖到單獨使用的導航欄

在絕大多數場景中,導航欄都是作為導航控制器的一部分使用的。但是有些情況下可能需要單獨使用導航欄來實現內容導航方法。單獨使用導航欄時,需要為其提供內容。與其他類型的視圖不同,不能直接將子視圖添加到導航欄,而需要使用navigationItem來指定要顯示的按鈕或者自定義視圖。navigationItemUINavigationItem類的實例對象,其持有用于在導航欄的左側、右側和中心指定視圖以及用于指定自定義提示字符串的屬性,如圖2-1所示。

導航欄管理著一個包含UINavigationItem對象的堆棧。堆棧主要用于支持導航控制器,可以使用它來實現我們自己的自定義導航界面。堆棧中最頂端的navigationItem是導航欄當前顯示內容所屬的navigationItem,使用其pushNavigationItem:animated:方法將新的navigationItem推入到堆棧中,使用popNavigationItemAnimated:方法從堆棧中彈出navigationItem

除了推入和彈出navigationItem之外,還可以直接使用導航欄的items屬性或者setItems:animated:方法設置堆棧的內容。可以在應用程序啟動時使用此方法將界面恢復到上次關閉應用程序前的狀態。下圖顯示了導航欄是如何管理navigationItem堆棧的:

圖2-2

單獨使用導航欄時,需要手動為導航欄配置委托對象,委托對象要遵循UINavigationBarDelegate協議。通過實現委托對象的委托方法,委托對象就能接收到導航欄發送的消息。這樣就能跟蹤何時推入navigationItem到堆棧中或者從堆棧中彈出navigationItem,并根據這些消息來更新應用程序的界面。

有關創建navigationItem的信息,可以參看UINavigationItem。有關委托對象的信息,可以參看UINavigationBarDelegate

自定義導航欄外觀

導航欄有兩種標準的外觀樣式:黑色文字配白色背景或者白色文字配黑色背景。使用其barStyle屬性來配置外觀樣式。對導航欄外觀樣式barStyle屬性的更改,會覆蓋導航欄從其他與外觀有關的屬性推斷出的顯示內容。

導航欄默認是半透明的,可以通過將其translucent屬性值設為NO來使導航欄不透明。

可以使用barTintColor屬性來設置導航欄背景色,設置此屬性會覆蓋從barStyle屬性推斷出的默認顏色。與所有UIView子類一樣,可以使用tintColor屬性來控制導航欄上控件內容的顏色,包括按鈕圖片和按鈕文字。

titleTextAttributes屬性用來指定標題文本外觀的,可以分別使用NSFontAttributeNameNSForegroundColorAttributeNameNSShadowAttributeName鍵為標題文本指定字體、文本顏色、文本陰影顏色和文本陰影偏移量。

使用setTitleVerticalPositionAdjustment:forBarMetrics:方法來調整標題在垂直方向上的位置,UIBarMetrics枚舉值定義了導航欄是否緊湊和是否含有提示文本,該方法會根據指定的UIBarMetrics枚舉值來調整導航欄的高度。下圖顯示了具有自定義的背景顏色、標題文本屬性和控件內容顏色的導航欄。

圖2-3

還可以提供自定義背景圖片和陰影圖片來完全定制導航欄的外觀,調用setBackgroundImage:forBarPosition:barMetrics:方法根據指定的UIBarPosition枚舉值和UIBarMetrics枚舉值來設置對應導航欄的背景圖片。UIBarPosition枚舉值定義了導航欄是在窗口底部還是在窗口頂部顯示的。

通過配置shadowImage屬性值來為導航欄提供自定義陰影圖片,但是自定義陰影圖片的前提條件是必須要自定義導航欄背景圖片。否則,將會使用默認的陰影圖片。下圖顯示了自定義背景圖片并自定義陰影圖片的導航欄,導航欄的位置值為UIBarPositionTopAttached,高度值為UIBarMetricsDefault

圖2-4

導航欄顏色切換、透明度漸變

應用程序在iOS 10以上系統運行時,使用Xcode調試應用程序時,查看半透明導航欄的視圖層,其子視圖信息如下圖所示:

圖3-1

如果導航欄不透明,視圖層就不會包含UIVisualEffectView視圖分支。如果導航欄使用了自定義背景,則會插入一個UIImageView視圖到_UIBarBackground視圖并位于最底層。另外,在iOS 10以下的系統中運行時,UIVisualEffectView子視圖層中的視圖會有所改變。

導航欄的外觀是由其_UIBarBackground子視圖決定的。調用官方提供的方法設置導航欄背景色時,實際調整的是_UIBarBackground子視圖的背景顏色,調用官方提供的方法設置導航欄自定義背景圖片時,實際上是在_UIBarBackground子視圖的最底層添加一個UIImageView視圖。

設置導航欄顏色

在視圖控制器跳轉過程中,UIKit框架會自動對導航欄上的子視圖執行一些操作,我們對導航欄上的子視圖執行的操作可能會被覆蓋掉。所以,為了能夠完全控制導航欄的背景色操作,可以在_UIBarBackground子視圖最底層手動添加一個子視圖,并通過改變這個子視圖的背景來控制導航欄的外觀背景,這樣就不會被官方的操作覆蓋掉。

設置導航欄透明度

UIKit框架沒有提供方法來直接修改導航欄的透明度,但我們已經知道導航欄的外觀由其_UIBarBackground子視圖決定。所以,調整_UIBarBackground視圖及其子視圖的透明度就能改變導航欄的透明度。但在iOS 10以上系統中,在push和pop視圖控制器時,UIKit框架會自動重置_UIBarBackground視圖的顏色和透明度等屬性。這會覆蓋掉我們對該視圖執行的修改,但我們可以通過方法交換來繞開UIKit框架的這種行為。

為導航欄添加轉場動畫

對視圖控制器執行push或者pop操作時,為了提高用戶體驗,通常會使用官方提供的轉場動畫。官方提供的轉場動畫有交互式和非交互式兩種類型。在執行push或者pop操作時,兩個視圖控制器的對應導航欄背景色不同,直接修改背景色在視覺上會顯得很突兀。這時候,就需要給導航欄背景色的切換加上動畫效果,讓其隨著push或者pop轉場動畫一起執行。

視圖控制器的轉場動畫協調器transitionCoordinator對象提供了animateAlongsideTransition:completion:animateAlongsideTransitionInView:animation:completion:方法來讓我們在UIKit框架執行標準的轉場動畫的同時,對其他視圖執行動畫。

Demo

示例代碼下載地址:https://github.com/Jen668/SJNavigationBarTransition

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

推薦閱讀更多精彩內容