UINavigationController這一篇就夠了

zhaobin545 7年前發布 | 14K 次閱讀 iOS開發 移動開發

(一)UINavigationController及其相關控件之間的關系

@interface UINavigationController : UIViewController
@property(nonatomic,readonly) UINavigationBar *navigationBar;

@interface UIViewController (UINavigationControllerItem) @property(nonatomic,readonly,strong) UINavigationItem *navigationItem;

@interface UINavigationBar : UIView @property(nullable, nonatomic,readonly,strong) UINavigationItem topItem; @property(nullable, nonatomic,readonly,strong) UINavigationItem backItem; @property(nullable,nonatomic,copy) NSArray<UINavigationItem > items;

@interface UINavigationItem : NSObject @property(nullable,nonatomic,strong) UIBarButtonItem backBarButtonItem @property(nullable,nonatomic,copy) NSArray<UIBarButtonItem > leftBarButtonItems; @property(nullable,nonatomic,copy) NSArray<UIBarButtonItem > rightBarButtonItems; @property(nullable, nonatomic,strong) UIBarButtonItem leftBarButtonItem; @property(nullable, nonatomic,strong) UIBarButtonItem *rightBarButtonItem;

@interface UIBarButtonItem : UIBarItem @property(nullable, nonatomic) SEL action;

@interface UIBarItem : NSObject @property(nullable, nonatomic,copy) NSString title; @property(nullable, nonatomic,strong) UIImage image;</code></pre>

通過對上述幾個類的屬性的羅列,我們可以做個總結

基本介紹

  • UIBarItem
    一個可以放置在Bar之上的所有小控件類的抽象類,可以設置標題,圖片等
  • UIBarButtonItem
    繼承UIBarItem,增加了動作以及目標等button的屬性。相當于放在UIToolBar或者UINavigationBar上的特殊的button。
  • UINavigationItem
    包含了title,prompt,titleView,leftBarButtonItem,rightBarButtonItem,backBarButonItem等當前頁面上所有的信息
  • UINavigationBar
    NavigaitonBar就是導航欄 主要對UINavigationItem進行棧管理 展示導航欄的外觀背景
  • UINavigationController
    包含了viewcontrollers、navigationbar、toolbar

關系綜述

  • UINavigationController是一個容器類,對ViewController進行棧管理,包含navigationBar。
  • UINavigationBar 即UINavigationController頂部的導航欄,主要負責外觀背景的展示,并對navigationItem進行棧管理
  • UINavigationItem是導航欄上顯示的具體的元素的一個抽象類,UINavigationController 通過Category的方法為ViewController添加了一個navigationItem,把UINavigationItem交由ViewController管理

    // Created on-demand so that a view controller may customize its navigation appearance.

這里引用 葉落寒 的一段介紹,更加的通俗易懂

通俗地說就是,UINavigationController是個容器,里面可以裝很多UIViewController。裝這么多UIViewController讓用戶怎么控制它們呢?總得有個工具吧,這個工具就是UINavigationBar。一個容器就這么一個bar,相當于控制臺吧。但是管理那么多UIViewController,控制臺上得按鈕啊、標題啊,都千篇一律是不是看起來太無聊了。為了解決這個問題,UINavigationController為每個UIViewController生成一個UINavigationItem,通過這個UINavigationItem可以改變控制臺“上面”的按鈕和標題。如果你不自定義UINavigationItem,UINavigationController會使用默認的;

(二)UINavigationController及其相關控件的屬性和方法

1. UIBarButtonItem

//初始化方法

  • (instancetype)init;
  • (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
  • (instancetype)initWithImage:(nullable UIImage )image landscapeImagePhone:(nullable UIImage )landscapeImagePhone style:(UIBarButtonItemStyle)style target:(nullable id)target action:(nullable SEL)action;
  • (instancetype)initWithTitle:(nullable NSString *)title style:(UIBarButtonItemStyle)style target:(nullable id)target action:(nullable SEL)action;
  • (instancetype)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(nullable id)target action:(nullable SEL)action;
  • (instancetype)initWithCustomView:(UIView *)customView;

@property(nonatomic) UIBarButtonItemStyle style; //類型 @property(nonatomic) CGFloat width; @property(nullable, nonatomic,copy) NSSet<NSString > possibleTitles; @property(nullable, nonatomic,strong) __kindof UIView customView; @property(nullable, nonatomic) SEL action; @property(nullable, nonatomic,weak) id target; @property(nullable, nonatomic,strong) UIColor tintColor

//為任意style的button設置背景圖片

  • (void)setBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics
  • (nullable UIImage *)backgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics

//為特定style的button設置背景圖片

  • (void)setBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state style:(UIBarButtonItemStyle)style barMetrics:(UIBarMetrics)barMetrics
  • (nullable UIImage *)backgroundImageForState:(UIControlState)state style:(UIBarButtonItemStyle)style barMetrics:(UIBarMetrics)barMetrics

//設置背景圖片垂直方向的偏移量

  • (void)setBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics
  • (CGFloat)backgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics

//設置標題的偏移量

  • (void)setTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics
  • (nullable UIImage *)backButtonBackgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics

//設置返回按鈕標題偏移量

  • (void)setBackButtonTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics
  • (UIOffset)backButtonTitlePositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics

//設置返回按鈕背景圖片在垂直方向上的偏移量

  • (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics
  • (CGFloat)backButtonBackgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics</code></pre>
    typedef NS_ENUM(NSInteger, UIBarButtonSystemItem) {
      UIBarButtonSystemItemDone,//顯示完成
      UIBarButtonSystemItemCancel,//顯示取消
      UIBarButtonSystemItemEdit,  //顯示編輯
      UIBarButtonSystemItemSave, //顯示保存 
      UIBarButtonSystemItemAdd,//顯示加號
      UIBarButtonSystemItemFlexibleSpace,//什么都不顯示,占位一個空間位置
      UIBarButtonSystemItemFixedSpace,//和上一個類似
      UIBarButtonSystemItemCompose,//顯示寫入按鈕
      UIBarButtonSystemItemReply,//顯示循環按鈕
      UIBarButtonSystemItemAction,//顯示活動按鈕
      UIBarButtonSystemItemOrganize,//顯示組合按鈕
      UIBarButtonSystemItemBookmarks,//顯示圖書按鈕
      UIBarButtonSystemItemSearch,//顯示查找按鈕
      UIBarButtonSystemItemRefresh,//顯示刷新按鈕
      UIBarButtonSystemItemStop,//顯示停止按鈕
      UIBarButtonSystemItemCamera,//顯示相機按鈕
      UIBarButtonSystemItemTrash,//顯示移除按鈕
      UIBarButtonSystemItemPlay,//顯示播放按鈕
      UIBarButtonSystemItemPause,//顯示暫停按鈕
      UIBarButtonSystemItemRewind,//顯示退后按鈕
      UIBarButtonSystemItemFastForward,//顯示前進按鈕
      UIBarButtonSystemItemUndo,//顯示消除按鈕
      UIBarButtonSystemItemRedo ,//顯示重做按鈕
      UIBarButtonSystemItemPageCurl ,//在tool上有效
    };

    2.UINavigationItem

    NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationItem : NSObject <NSCoding>
    //初始化
  • (instancetype)initWithTitle:(NSString *)title NS_DESIGNATED_INITIALIZER;
  • (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

//設置導航欄中間的內容標題 @property(nullable, nonatomic,copy) NSString title;
//設置導航欄中間的內容視圖
@property(nullable, nonatomic,strong) UIView
titleView;
//提示 @property(nullable,nonatomic,copy) NSString prompt;
//返回 @property(nullable,nonatomic,strong) UIBarButtonItem
backBarButtonItem; //是否隱藏返回Button @property(nonatomic,assign) BOOL hidesBackButton;

  • (void)setHidesBackButton:(BOOL)hidesBackButton animated:(BOOL)animated;

//左邊數組Item @property(nullable,nonatomic,copy) NSArray<UIBarButtonItem > leftBarButtonItems NS_AVAILABLE_IOS(5_0); //右邊數組Item @property(nullable,nonatomic,copy) NSArray<UIBarButtonItem > rightBarButtonItems NS_AVAILABLE_IOS(5_0);

  • (void)setLeftBarButtonItems:(nullable NSArray<UIBarButtonItem > )items animated:(BOOL)animated NS_AVAILABLE_IOS(5_0);
  • (void)setRightBarButtonItems:(nullable NSArray<UIBarButtonItem > )items animated:(BOOL)animated NS_AVAILABLE_IOS(5_0);

//通過指定該屬性為YES,可以讓leftBarButtonItem和backBarButtonItem同時顯示,其中leftBarButtonItem顯示在backBarButtonItem的右邊 默認值為NO @property(nonatomic) BOOL leftItemsSupplementBackButton NS_AVAILABLE_IOS(5_0);

//左邊Item @property(nullable, nonatomic,strong) UIBarButtonItem leftBarButtonItem; //右邊Item @property(nullable, nonatomic,strong) UIBarButtonItem rightBarButtonItem;

  • (void)setLeftBarButtonItem:(nullable UIBarButtonItem *)item animated:(BOOL)animated;
  • (void)setRightBarButtonItem:(nullable UIBarButtonItem *)item animated:(BOOL)animated; @end</code></pre>

    prompt 是一個NSString類型描述,注意添加該描述以后NavigationBar的高度會增加30,總的高度會變成74(不管當前方向是Portrait還是Landscape,此模式下navgationbar都使用高度44加上prompt30的方式進行顯示)。

    如:

    self.navigationItem.prompt=@"這是什么?";
    self.title=@"HAH";

    prompt.png

    3.UINavigationBar

    NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationBar : UIView <NSCoding, UIBarPositioning> 

//UIBarStyleDefault 灰色背景 白色文字 UIBarStyleBlack 純黑色背景 白色文字 @property(nonatomic,assign) UIBarStyle barStyle; @property(nullable,nonatomic,weak) id<UINavigationBarDelegate> delegate; //Translucent設置成透明度,設置成YES會有一種模糊效果 @property(nonatomic,assign,getter=isTranslucent) BOOL translucent NS_AVAILABLE_IOS(3_0) UI_APPEARANCE_SELECTOR; //UINavigationBar上面不只是簡單的顯示標題,它也將標題進行了堆棧的管理,每一個標題抽象為的對象在iOS系統中是UINavigationItem對象,我們可以通過push與pop操作管理item組。 //向棧中添加一個item,上一個item會被推向導航欄的左側,變為pop按鈕,會有一個動畫效果

  • (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated; //pop一個item
  • (nullable UINavigationItem )popNavigationItemAnimated:(BOOL)animated; //當前push到最上層的item @property(nullable, nonatomic,readonly,strong) UINavigationItem topItem; //僅次于最上層的item,一般式被推向導航欄左側的item @property(nullable, nonatomic,readonly,strong) UINavigationItem backItem; //獲取堆棧中所有item的數組 @property(nullable,nonatomic,copy) NSArray<UINavigationItem > *items; //設置一組item
  • (void)setItems:(nullable NSArray<UINavigationItem > )items animated:(BOOL)animated;

//系統類型按鈕文字顏色 @property(null_resettable, nonatomic,strong) UIColor *tintColor;

//通過barTintColor來設置背景色 @property(nullable, nonatomic,strong) UIColor *barTintColor NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;

//設置工具欄背景和陰影圖案

  • (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarPosition:(UIBarPosition)barPosition barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;
  • (nullable UIImage *)backgroundImageForBarPosition:(UIBarPosition)barPosition barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;

//通過背景圖片來設置導航欄的外觀

  • (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
  • (nullable UIImage *)backgroundImageForBarMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;

//背景陰影圖片 - 即分割線 @property(nullable, nonatomic,strong) UIImage *shadowImage NS_AVAILABLE_IOS(6_0) UI_APPEARANCE_SELECTOR;

//標題的富文本 @property(nullable,nonatomic,copy) NSDictionary<NSString ,id> titleTextAttributes NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;

//標題垂直偏移

  • (void)setTitleVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
  • (CGFloat)titleVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;

//設置返回按鈕的圖片 @property(nullable,nonatomic,strong) UIImage backIndicatorImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR; @property(nullable,nonatomic,strong) UIImage backIndicatorTransitionMaskImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR; @end</code></pre>

4.UINavigationController

NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationController : UIViewController

//UINavigationController初始化,自定義NavigationBar,自定義toolbar

  • (instancetype)initWithNavigationBarClass:(nullable Class)navigationBarClass toolbarClass:(nullable Class)toolbarClass NS_AVAILABLE_IOS(5_0);

//UINavigationController初始化,導航控制器的根控制器

  • (instancetype)initWithRootViewController:(UIViewController *)rootViewController;

//壓棧:將目標控制器壓入棧中

  • (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;

//彈棧:將棧頂控制器從棧中彈出

  • (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated;

//彈棧:彈到指定的目標控制器

  • (nullable NSArray<__kindof UIViewController > )popToViewController:(UIViewController *)viewController animated:(BOOL)animated;

//彈棧:彈到根控制器

  • (nullable NSArray<__kindof UIViewController > )popToRootViewControllerAnimated:(BOOL)animated; //導航棧的棧頂視圖 只讀 就是某個導航棧的棧頂視圖,和導航息息相關 @property(nullable, nonatomic,readonly,strong) UIViewController topViewController; //當前顯示的控制器 只讀 visibleViewController和哪個導航棧沒有關系,只是當前顯示的控制器,也就是說任意一個導航的visibleViewController所返回的值應該是一樣的 @property(nullable, nonatomic,readonly,strong) UIViewController visibleViewController;

//棧里的視圖控制器數組 @property(nonatomic,copy) NSArray<__kindof UIViewController > viewControllers;

//替換棧中的視圖控制器數組

  • (void)setViewControllers:(NSArray<UIViewController > )viewControllers animated:(BOOL)animated NS_AVAILABLE_IOS(3_0);

//是否隱藏導航欄 @property(nonatomic,getter=isNavigationBarHidden) BOOL navigationBarHidden;

//設置導航欄隱藏 是否有動畫

  • (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;

//導航欄 @property(nonatomic,readonly) UINavigationBar *navigationBar;

//toolbar是否隱藏 @property(nonatomic,getter=isToolbarHidden) BOOL toolbarHidden NS_AVAILABLE_IOS(3_0);

//toolbar是否隱藏 是否有動畫

  • (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated NS_AVAILABLE_IOS(3_0);

//toolbar對象 @property(null_resettable,nonatomic,readonly) UIToolbar *toolbar NS_AVAILABLE_IOS(3_0);

//委托 @property(nullable, nonatomic, weak) id<UINavigationControllerDelegate> delegate;

//邊緣側滑返回手勢 @property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer NS_AVAILABLE_IOS(7_0);

//展示視圖控制器

  • (void)showViewController:(UIViewController *)vc sender:(nullable id)sender NS_AVAILABLE_IOS(8_0); // Interpreted as pushViewController:animated:

//輸入鍵盤出現時將導航欄隱藏 IOS8特性 @property (nonatomic, readwrite, assign) BOOL hidesBarsWhenKeyboardAppears NS_AVAILABLE_IOS(8_0);

//滾動頁面時隱藏Bar IOS8特性 @property (nonatomic, readwrite, assign) BOOL hidesBarsOnSwipe NS_AVAILABLE_IOS(8_0);

//獲取能夠隱藏navigationBar的滑動手勢 只讀 @property (nonatomic, readonly, strong) UIPanGestureRecognizer *barHideOnSwipeGestureRecognizer NS_AVAILABLE_IOS(8_0);

//當設置為true時,橫向方向時隱藏NavigationBar @property (nonatomic, readwrite, assign) BOOL hidesBarsWhenVerticallyCompact NS_AVAILABLE_IOS(8_0);

//當設置為true時,如果有沒處理的點擊手勢就會隱藏和現實navigationBar @property (nonatomic, readwrite, assign) BOOL hidesBarsOnTap NS_AVAILABLE_IOS(8_0);

//獲取能夠隱藏navigationBar的點擊手勢 只讀 @property (nonatomic, readonly, assign) UITapGestureRecognizer *barHideOnTapGestureRecognizer NS_AVAILABLE_IOS(8_0);

@end</code></pre>

@interface UIViewController (UINavigationControllerItem)
//導航欄上面用戶自定義視圖
@property(nonatomic,readonly,strong) UINavigationItem *navigationItem; 
//推送時隱藏bottom
@property(nonatomic) BOOL hidesBottomBarWhenPushed;
//下級視圖的導航控制器
@property(nullable, nonatomic,readonly,strong) UINavigationController *navigationController; 
@end
@interface UIViewController (UINavigationControllerContextualToolbarItems)
//屬性設置工具條中包含的按鈕
@property (nullable, nonatomic, strong) NSArray<__kindof UIBarButtonItem > toolbarItems NS_AVAILABLE_IOS(3_0);

  • (void)setToolbarItems:(nullable NSArray<UIBarButtonItem > )toolbarItems animated:(BOOL)animated NS_AVAILABLE_IOS(3_0); @end</code></pre>

    (三)實際開發過程中的一些問題

    1.UINavigationBar的背景顏色

    -(void)changeNavigationBarBackgroundColor {
      //背景色
      self.navigationBar.barTintColor = [UIColor blueColor];

    //title字體 //[self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor lightGrayColor],NSFontAttributeName:[UIFont systemFontOfSize:17]}];

    //修改UIBarButtonItem 圖片 title顏色 self.navigationBar.tintColor = [UIColor greenColor];

    //是否半透明 當為YES時 設置的導航欄背景顏色會和實際rgb值有誤差 self.navigationBar.translucent = NO;

    //如果想要半透明效果 顏色沒有色差 可以通過設置背景圖片的方法 背景圖片會覆蓋barTintColor //- (void)setBackgroundImage:(nullable UIImage )backgroundImage forBarMetrics:(UIBarMetrics)barMetrics }</code></pre>

    2.UINavigationBar底部的shadowImage

    Apple官方對shadowImage有這樣的介紹:

    / Default is nil. When non-nil, a custom shadow image to show instead of the default shadow image. For a custom shadow to be shown, a custom background image must also be set with -setBackgroundImage:forBarMetrics: (if the default background image is used, the default shadow image will be used). /

    設置shadowImage必須先setBackgroundImage,否則無法實現效果

    -(void)changeNavigationBarBottonLine {
      //設置底部line顏色時需要同時設置backgroundImage即導航欄的背景圖片 否則沒有效果
      [self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
      [self.navigationBar setShadowImage:[self imageWithColor:[UIColor redColor]]];
      //此處設置透明顏色的image,底部line即可隱藏,但此種方法隱藏,沒有辦法再顯示 下面方法通過找到該view 控制其hidden屬性
      //[self reducibilityHiddenNavogationBarLine];
    }

    找到該imageView設置起Hidden為YES

    -(void)reducibilityHiddenNavogationBarLine {
      UIImageView  imageView = [self findLineImageViewUnder:self.navigationBar];
      if (imageView) {

     imageView.hidden = YES;
    

    } }</code></pre>

    找到該imageView

    -(UIImageView )findLineImageViewUnder:(UIView )view {
      if ([view isKindOfClass:[UIImageView class]] && view.bounds.size.height <= 1.0) {

      return (UIImageView *)view;
    

    } for (UIView * subView in view.subviews) {

      UIImageView * imageView = [self findLineImageViewUnder:subView];
      if (imageView) {
          return imageView;
      }
    

    } return nil; }</code></pre>

    3.自定義導航欄的返回按鈕

    @property(nonatomic,readonly) UINavigationBar *navigationBar;// The navigation bar managed by the controller. Pushing, popping or setting navigation items on a managed navigation bar is not supported.

    受controller管理的navigationBar 不支持對navigation items操作,所以此處對返回按鈕的操作是在ViewController完成的,以下代碼中self表示ViewController

    Apple官方對setBackIndicatorImage和setBackIndicatorTransitionMaskImage做了如下解釋,必須同時設置才能生效

    /*
    The back indicator image is shown beside the back button.
    The back indicator transition mask image is used as a mask for content during push and pop transitions
    Note: These properties must both be set if you want to customize the back indicator image.
    */

    1.自定義文字+圖片

    -(void)createCustomBackBarItem {

    //修改圖片文字顏色 self.navigationController.navigationBar.tintColor = [UIColor whiteColor];

    //替換圖片 [self.navigationController.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"erwema"]]; [self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"erwema"]];

    //設置文字 UIBarButtonItem backBarItem = [[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil]; self.navigationItem.backBarButtonItem = backBarItem; }</code></pre>

    注意:

    對backBarButtonItem的修改是在當前viewController前一個頁面完成的,在當前頁面修改針對下一個viewController的navigationItem生效

    2.不顯示文字

    設置Title在Y方向上的偏移量,使其移除屏幕,該方法在第一次進入時會有個文字移動的動畫效果,效果不好,不推薦使用

    [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -100) forBarMetrics:UIBarMetricsDefault];

    3.使用leftBarButtonItem替代backBarButtonItem

    使用這種方法,不能使用邊緣滑動返回手勢,且不能同時設置圖片和標題

    -(void)setLeftBarItemBack
    {
      UIBarButtonItem leftBarBtnItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"back"] style:UIBarButtonItemStylePlain target:self action:@selector(clickLeftBarBtnItem:)];
      [self.navigationItem setLeftBarButtonItem:leftBarBtnItem animated:YES];
      self.navigationItem.leftBarButtonItem.tintColor = NavigationLeftBackColor;
    }

/**

  • 導航條leftBarBtn事件 */
    • (void)clickLeftBarBtnItem:(UIBarButtonItem )sender { [self.navigationController popViewControllerAnimated:YES]; }</code></pre>

      4.使用CustomView的方法

      此方法不適于backBarButtonItem,只能用于leftBarButtonItem

      注意:

      1.如果B視圖有一個自定義的左側按鈕(leftBarButtonItem),則會顯示這個自定義按鈕;

      2.如果B沒有自定義按鈕,但是A視圖的backBarButtonItem屬性有自定義項,則顯示這個自定義項;

      3.如果前2條都沒有,則默認顯示一個后退按鈕,后退按鈕的標題是A視圖的標題;

      此處注意:

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

      使用3、4方法,邊緣返回會失效,此時加上這句代碼依然可以實現邊緣滑動返回

      self.navigationController.interactivePopGestureRecognizer.delegate = self;

      這里推薦使用 FDFullscreenPopGesture 全屏滑動手勢返回,減少工作量。

      4.navigationBar偶爾顯示上一個頁面的navigationBar

      一般情況下都是正常的。但是在偶然情況下,會出現在進入新界面后,新界面的navigationBar會突然消失,出現的還是上一個界面的 navigationBar。從此以后,navigationBar 全亂了, kill 掉重新進,恢復正常。

      原因:

      一般我們會打點調用navigationBarHidden的屬性來設置導航欄是否隱藏,這種方法是不帶動畫效果的。這樣偶爾就會導致錯亂,這應該是一個系統的bug,所以應盡量使用

      [self.navigationController setNavigationBarHidden:YES animated:YES];

      來設置navigationBar的Hidden屬性。

      5.修改系統navigationBar的高度

      UINavigationBar  navigatioBar = self.navigationController.navigationBar;
      CGFloat navBarHeight = 100.f;
      CGRect frame = CGRectMake(0.0f, 0.0f, 320.0f, navBarHeight);
      [navigatioBar setFrame:frame];</code></pre> 
      

      此種方法經測試只有在非rootViewController中才能生效,這樣在第一次進入根視圖的時候navigationBar并不會變高,不知有沒有人知道該如何解決,歡迎賜教。

      6.易混淆知識點

      1.self.title、self.navigationItem.title、self.tabBarItem.title之間的關系

      一目了然

      self.navigationItem.title = @"my title"; //sets navigation bar title.
      self.tabBarItem.title = @"my title"; //sets tab bar title.
      self.title = @"my title"; //sets both of these.
      1. 如果當前VC通過 self.navigationItem.titleView指定了自定義的titleView,系統將會顯示指定的titleView,設置self.title、self.navigationItem.title不會改變導航欄的標題。
      2. 如果當前VC沒有指定titleView,系統則會根據當前VC的title或者當前VC的navigationItem.title的內容創建一個UILabel并顯示。
      3. self.title會重寫navigationItem和tabBarItem的title。

      2.self.navigationItem,self.navigationController.navigationItem的關系

      navigationItem是UIViewController的一個屬性,navigationController繼承UIViewController,自然會繼承viewControoler的navigationItem屬性。此處self.navigationController.navigationItem是應該被忽視的。navigationItem直接由viewController管理。

      3.UIBarMetrics和UIBarPosition

      typedef NS_ENUM(NSInteger, UIBarMetrics) {
      UIBarMetricsDefault, //橫屏
      UIBarMetricsCompact,//豎屏
      UIBarMetricsDefaultPrompt = 101, //橫屏且設置了prompt屬性  Applicable only in bars with the prompt property, such as UINavigationBar and UISearchBar
      UIBarMetricsCompactPrompt, //豎屏且設置了prompt屬性
      };

typedef NS_ENUM(NSInteger, UIBarPosition) { UIBarPositionAny = 0, //Bar在任何位置 UIBarPositionBottom = 1, //Bar在底部 UIBarPositionTop = 2, //Bar在頂部 UIBarPositionTopAttached = 3, //Bar在頂部,且他的背景擴展到statusBar的區域 } NS_ENUM_AVAILABLE_IOS(7_0);</code></pre>

不正之處,還望多多指教!

參考文章

你真的了解UINavigationController嗎?

UINavigationItem UINavigationBar 關系分析

 

來自:http://www.jianshu.com/p/69b4e7bed7d4

 

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