IOS之UINavigationController

有一陣子沒有寫隨筆,感覺有點兒手生。一個多月以後終於又一次坐下來靜下心寫隨筆,記錄自己的學習筆記,也希望能夠幫到大家。

  廢話少說回到正題,UINavigationController是IOS編程中比較常用的一種容器view controller,很多系統的控件(如UIImagePickerViewController)以及很多有名的APP中(如qq,系統相冊等)都有用到。說是使用詳解,其實我只會介紹幾個自認爲比較重要或者容易放錯的地方進行講解,下面讓我們挨個探探究竟:

  首先上一張圖(來自蘋果官方文檔):

                        UINavigationController view層級

1、navigationItem

  我們都知道navigationItem是UIViewController的一個屬性,這個屬性是爲UINavigationController服務的。文檔中是這麼解釋的“The navigation item used to represent the view controller in a parent’s navigation bar. (read-only)”,即navigation item在navigation Bar代表一個viewController,具體一點兒來說就是每一個加到navigationController的viewController都會有一個對應的navigationItem,該對象由viewController以懶加載的方式創建,稍後我們可以在對象中堆navigationItem進行配置,可以設置leftBarButtonItem, rightBarButtonItem, backBarButtonItem, title以及prompt等屬性。前三個每一個都是一個UIBarButtonItem對象,最後兩個屬性是一個NSString類型描述,注意添加該描述以後NavigationBar的高度會增加30,總的高度會變成74(不管當前方向是Portrait還是Landscape,此模式下navgationbar都使用高度44加上prompt30的方式進行顯示)。當然如果覺得只是設置文字的title不夠爽,你還可以通過titleview屬性指定一個定製的titleview,這樣你就可以隨心所欲了,當然注意指定的titleview的frame大小,不要顯示出界。

  舉個簡單的例子:

複製代碼
// set rightItem
UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithTitle:@"Root" style:UIBarButtonItemStyleBordered target:self action:@selector(popToRootVC)];
childOne.navigationItem.rightBarButtonItem = rightItem;
[rightItem release];
    
// when you design a prompt for navigationbar, the hiehgt of navigationbar will becaome 74, ignore the orientation
childOne.navigationItem.prompt = @"Hello, im the prompt";
複製代碼

  這段代碼設置了navigationItem的rightBarButtonItem,同時設置了prompt信息。

 

2、titleTextAttributes(ios5.0以後可用)

  這是UINavigationBar的一個屬性,通過它你可以設置title部分的字體,這個屬性定義如下:

/* You may specify the font, text color, text shadow color, and text shadow offset for the title in the text attributes dictionary, using the keys found in UIStringDrawing.h.
 */
@property(nonatomic,copy) NSDictionary *titleTextAttributes __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0) UI_APPEARANCE_SELECTOR;

  它的dictionary的key定義以及其對應的value類型如下:

//    Keys for Text Attributes Dictionaries
//    NSString *const UITextAttributeFont;                       value: UIFont
//    NSString *const UITextAttributeTextColor;                 value: UIColor
//    NSString *const UITextAttributeTextShadowColor;       value: UIColor
//    NSString *const UITextAttributeTextShadowOffset;      value: NSValue wrapping a UIOffset struct.

  下面看一個簡單的例子:

NSDictionary *dict = [NSDictionary dictionaryWithObject:[UIColor yellowColor] forKey:UITextAttributeTextColor];
childOne.navigationController.navigationBar.titleTextAttributes = dict;

  這個例子就是設置title的字體顏色爲黃色,怎麼樣簡單吧。

 

3、wantsFullScreenLayout

  viewController的一個屬性,這個屬性默認值是NO,如果設置爲YES的話,如果statusbar,navigationbar, toolbar是半透明的話,viewController的view就會縮放延伸到它們下面,但注意一點兒tabBar不在範圍內,即無論該屬性是否爲YES,view都不會覆蓋到tabbar的下方。

 

4、navigationBar中的stack

  這個屬性可以算是UINavigationController的靈魂之一,它維護了一個和UINavigationController中viewControllers對應的navigationItem的stack,該stack用於負責navigationbar的刷新。“注意:如果navigationbar中navigationItem的stack和對應的NavigationController中viewController的stack是一一對應的關係,如果兩個stack不同步就會拋出異常。

  下面舉個簡單拋出異常的例子:

SvNavChildViewController *childOne = [[SvNavChildViewController alloc] initWithTitle:@"First" content:@"1"];
[self.navigationController pushViewController:childOne animated:NO];
[childOne release];
    
// raise exception when the stack of navigationbar and navigationController was not correspond
[self.navigationController.navigationBar popNavigationItemAnimated:NO];

  當pushViewcontroller的之後,強制把navigationBar中的navigationItem pop一個出去,程序立馬掛起。當然這純粹只是爲了驗證問題,我想一般的碼農沒有人會這麼寫的。

 

5、navigationBar的刷新

  通過前面介紹的內容,我們知道navigationBar中包含了這幾個重要組成部分:leftBarButtonItem, rightBarButtonItem, backBarButtonItem, title。當一個view controller添加到navigationController以後,navigationBar的顯示遵循一下幾個原則:

  1)、Left side of the navigationBar

  a)如果當前的viewController設置了leftBarButtonItem,則顯示當前VC所自帶的leftBarButtonItem。

  b)如果當前的viewController沒有設置leftBarButtonItem,且當前VC不是rootVC的時候,則顯示前一層VC的backBarButtonItem。如果前一層的VC沒有顯示的指定backBarButtonItem的話,系統將會根據前一層VC的title屬性自動生成一個back按鈕,並顯示出來。

  c)如果當前的viewController沒有設置leftBarButtonItem,且當前VC已是rootVC的時候,左邊將不顯示任何東西。

  此處注意:5.0中新增加了一個屬性leftItemsSupplementBackButton,通過指定該屬性爲YES,可以讓leftBarButtonItem和backBarButtonItem同時顯示,其中leftBarButtonItem顯示在backBarButtonItem的右邊。

  2)、title部分

  a)如果當前VC通過 .navigationItem.titleView指定了自定義的titleView,系統將會顯示指定的titleView,此處要注意自定義titleView的高度不要超過navigationBar的高度,否則會顯示出界。

  b)如果當前VC沒有指定titleView,系統則會根據當前VC的title或者當前VC的navigationItem.title的內容創建一個UILabel並顯示,其中如果指定了navigationItem.title的話,則優先顯示navigationItem.title的內容。

  3)、Right side of the navigationBar

  a)如果當前VC指定了rightBarButtonItem的話,則顯示指定的內容。

  b)如果當前VC沒有指定rightBarButtonItem的話,則不顯示任何東西。

 

6、Toolbar

  navigationController自帶了一個工具欄,通過設置 self.navigationController.toolbarHidden = NO來顯示工具欄,工具欄中的內容可以通過viewController的toolbarItems來設置,顯示的順序和設置的NSArray中存放的順序一致,其中每一個數據都一個UIBarButtonItem對象,可以使用系統提供的很多常用風格的對象,也可以根據需求進行自定義。

  設置Toolbar內容的例子:

複製代碼
// test ToolBar
UIBarButtonItem *one = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:nil action:nil];
UIBarButtonItem *two = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:nil action:nil];
UIBarButtonItem *three = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:nil action:nil];
UIBarButtonItem *four = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:nil action:nil];
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[childOne setToolbarItems:[NSArray arrayWithObjects:flexItem, one, flexItem, two, flexItem, three, flexItem, four, flexItem, nil]];
[one release];
[two release];
[three release];
[four release];
[flexItem release];
    
childOne.navigationController.toolbarHidden = NO;
複製代碼

 

7、UINavigationControllerDelegate

  這個代理真的很簡單,就是當一個viewController要顯示的時候通知一下外面,給你一個機會進行設置,包含如下兩個函數:

// Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

  當你需要對某些將要顯示的viewController進行修改的話,可實現該代理。

 

8、UINavigationController的viewControllers屬性

  通過該屬性我們可以實現一次性替換整個navigationController的層次, 這個過程如果通過setViewControllers:animated:來設置,並指定動畫爲YES的畫,動畫將會從當前的navigationController所顯示的vc跳轉到所設置的目標viewController的最頂層的那個VC,而中間其他的VC將會被直接從VC層級中移除和添加進來(沒有動畫)。

 

9、topViewController Vs visibleViewController

  topViewController代表當前navigation棧中最上層的VC,而visibleViewController代表當前可見的VC,它可能是topViewController,也可能是當前topViewController present出來的VC。因此UINavigationController的這兩個屬性通常情況下是一樣,但也有可能不同。

  ------------------(完)

發佈了63 篇原創文章 · 獲贊 1 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章