IOS開發之UINavigationController詳解

jopen 10年前發布 | 70K 次閱讀 iOS開發 移動開發 UINavigationController

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

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

 IOS開發之UINavigationController詳解

                                                  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的這兩個屬性通常情況下是一樣,但也有可能不同。


 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!