IOS-UINavigationController詳解

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

@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;

通過對上述幾個類的屬性的羅列赘艳,我們可以做個總結(jié)

基本介紹
  • UIBarItem
    一個可以放置在Bar之上的所有小控件類的抽象類,可以設(shè)置標題筐喳,圖片等
  • UIBarButtonItem
    繼承UIBarItem,增加了動作以及目標等button的屬性袜香。相當于放在UIToolBar或者UINavigationBar上的特殊的button动壤。
  • UINavigationItem
    包含了title,prompt,titleView,leftBarButtonItem,rightBarButtonItem,backBarButonItem等當前頁面上所有的信息
  • UINavigationBar
    NavigaitonBar就是導航欄 主要對UINavigationItem進行棧管理 展示導航欄的外觀背景
  • UINavigationController
    包含了viewcontrollers咳榜、navigationbar牢撼、toolbar
關(guān)系綜述
  • 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及其相關(guān)控件的屬性和方法

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設(shè)置背景圖片
- (void)setBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics
- (nullable UIImage *)backgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics

//為特定style的button設(shè)置背景圖片
- (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


//設(shè)置背景圖片垂直方向的偏移量
- (void)setBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics
- (CGFloat)backgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics

//設(shè)置標題的偏移量
- (void)setTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics
- (nullable UIImage *)backButtonBackgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics

//設(shè)置返回按鈕標題偏移量
- (void)setBackButtonTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics
- (UIOffset)backButtonTitlePositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics

//設(shè)置返回按鈕背景圖片在垂直方向上的偏移量
- (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics
- (CGFloat)backButtonBackgroundVerticalPositionAdjustmentForBarMetrics:(UIBarMetrics)barMetrics
typedef NS_ENUM(NSInteger, UIBarButtonSystemItem) {
    UIBarButtonSystemItemDone,//顯示完成
    UIBarButtonSystemItemCancel,//顯示取消
    UIBarButtonSystemItemEdit,  //顯示編輯
    UIBarButtonSystemItemSave, //顯示保存 
    UIBarButtonSystemItemAdd,//顯示加號
    UIBarButtonSystemItemFlexibleSpace,//什么都不顯示壶笼,占位一個空間位置
    UIBarButtonSystemItemFixedSpace,//和上一個類似
    UIBarButtonSystemItemCompose,//顯示寫入按鈕
    UIBarButtonSystemItemReply,//顯示循環(huán)按鈕
    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;

//設(shè)置導航欄中間的內(nèi)容標題
@property(nullable, nonatomic,copy)   NSString        *title;         
//設(shè)置導航欄中間的內(nèi)容視圖    
@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;

//左邊數(shù)組Item
@property(nullable,nonatomic,copy) NSArray<UIBarButtonItem *> *leftBarButtonItems NS_AVAILABLE_IOS(5_0);
//右邊數(shù)組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同時顯示,其中l(wèi)eftBarButtonItem顯示在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

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設(shè)置成透明度,設(shè)置成YES會有一種模糊效果
@property(nonatomic,assign,getter=isTranslucent) BOOL translucent NS_AVAILABLE_IOS(3_0) UI_APPEARANCE_SELECTOR; 
//UINavigationBar上面不只是簡單的顯示標題,它也將標題進行了堆棧的管理鹦筹,每一個標題抽象為的對象在iOS系統(tǒng)中是UINavigationItem對象铝阐,我們可以通過push與pop操作管理item組。
//向棧中添加一個item铐拐,上一個item會被推向?qū)Ш綑诘淖髠?cè)徘键,變?yōu)閜op按鈕练对,會有一個動畫效果
- (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated;
//pop一個item
- (nullable UINavigationItem *)popNavigationItemAnimated:(BOOL)animated; 
//當前push到最上層的item
@property(nullable, nonatomic,readonly,strong) UINavigationItem *topItem;
//僅次于最上層的item,一般式被推向?qū)Ш綑谧髠?cè)的item
@property(nullable, nonatomic,readonly,strong) UINavigationItem *backItem;
//獲取堆棧中所有item的數(shù)組
@property(nullable,nonatomic,copy) NSArray<UINavigationItem *> *items;
//設(shè)置一組item
- (void)setItems:(nullable NSArray<UINavigationItem *> *)items animated:(BOOL)animated; 

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

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

//設(shè)置工具欄背景和陰影圖案
- (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;

//通過背景圖片來設(shè)置導航欄的外觀
- (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;

//設(shè)置返回按鈕的圖片
@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

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;
//導航棧的棧頂視圖 只讀 就是某個導航棧的棧頂視圖吹害,和導航息息相關(guān)
@property(nullable, nonatomic,readonly,strong) UIViewController *topViewController; 
//當前顯示的控制器 只讀 visibleViewController和哪個導航棧沒有關(guān)系螟凭,只是當前顯示的控制器,也就是說任意一個導航的visibleViewController所返回的值應該是一樣的
@property(nullable, nonatomic,readonly,strong) UIViewController *visibleViewController;

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

//替換棧中的視圖控制器數(shù)組
- (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers animated:(BOOL)animated NS_AVAILABLE_IOS(3_0); 

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

//設(shè)置導航欄隱藏 是否有動畫
- (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;

//邊緣側(cè)滑返回手勢
@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:

//輸入鍵盤出現(xiàn)時將導航欄隱藏 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);

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

//當設(shè)置為true時,如果有沒處理的點擊手勢就會隱藏和現(xiàn)實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
@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)
//屬性設(shè)置工具條中包含的按鈕
@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

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

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時 設(shè)置的導航欄背景顏色會和實際rgb值有誤差
    self.navigationBar.translucent = NO;

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

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).
*/

設(shè)置shadowImage必須先setBackgroundImage,否則無法實現(xiàn)效果

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

找到該imageView設(shè)置起Hidden為YES

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

找到該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;
}

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做了如下解釋辕棚,必須同時設(shè)置才能生效

/*
 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"]];
    
    //設(shè)置文字
    UIBarButtonItem * backBarItem = [[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil];
    self.navigationItem.backBarButtonItem = backBarItem;
}

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

2.不顯示文字
設(shè)置Title在Y方向上的偏移量补君,使其移除屏幕挽铁,該方法在第一次進入時會有個文字移動的動畫效果叽掘,效果不好更扁,不推薦使用

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

3.使用leftBarButtonItem替代backBarButtonItem
使用這種方法浓镜,不能使用邊緣滑動返回手勢膛薛,且不能同時設(shè)置圖片和標題

-(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];
}

4.使用CustomView的方法
此方法不適于backBarButtonItem哄啄,只能用于leftBarButtonItem

注意:
1.如果B視圖有一個自定義的左側(cè)按鈕(leftBarButtonItem)咨跌,則會顯示這個自定義按鈕虑润;
2.如果B沒有自定義按鈕拳喻,但是A視圖的backBarButtonItem屬性有自定義項冗澈,則顯示這個自定義項亚亲;
3.如果前2條都沒有腐缤,則默認顯示一個后退按鈕岭粤,后退按鈕的標題是A視圖的標題剃浇;


此處注意:
5.0中新增加了一個屬性leftItemsSupplementBackButton虎囚,通過指定該屬性為YES,可以讓leftBarButtonItem和backBarButtonItem同時顯示圃伶,其中l(wèi)eftBarButtonItem顯示在backBarButtonItem的右邊留攒。

使用3炼邀、4方法拭宁,邊緣返回會失效杰标,此時加上這句代碼依然可以實現(xiàn)邊緣滑動返回

    self.navigationController.interactivePopGestureRecognizer.delegate = self;

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

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

一般情況下都是正常的袜漩。但是在偶然情況下宙攻,會出現(xiàn)在進入新界面后座掘,新界面的navigationBar會突然消失溢陪,出現(xiàn)的還是上一個界面的 navigationBar嬉愧。從此以后喉前,navigationBar 全亂了卵迂, kill 掉重新進见咒,恢復正常。
原因:
一般我們會打點調(diào)用navigationBarHidden的屬性來設(shè)置導航欄是否隱藏缤言,這種方法是不帶動畫效果的胆萧。這樣偶爾就會導致錯亂跌穗,這應該是一個系統(tǒng)的bug,所以應盡量使用

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

來設(shè)置navigationBar的Hidden屬性蚌吸。

5.修改系統(tǒng)navigationBar的高度

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

此種方法經(jīng)測試只有在非rootViewController中才能生效羹唠,這樣在第一次進入根視圖的時候navigationBar并不會變高娄昆,不知有沒有人知道該如何解決稿黄,歡迎賜教杆怕。

6.易混淆知識點

1.self.title陵珍、self.navigationItem.title互纯、self.tabBarItem.title之間的關(guān)系

一目了然

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留潦,系統(tǒng)將會顯示指定的titleView,設(shè)置self.title兔院、self.navigationItem.title不會改變導航欄的標題坊萝。
  1. 如果當前VC沒有指定titleView,系統(tǒng)則會根據(jù)當前VC的title或者當前VC的navigationItem.title的內(nèi)容創(chuàng)建一個UILabel并顯示菩鲜。
  2. self.title會重寫navigationItem和tabBarItem的title接校。

2.self.navigationItem,self.navigationController.navigationItem的關(guān)系

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

3.UIBarMetrics和UIBarPosition

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

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

不正之處洗鸵,還望多多指教膘滨!

參考文章
你真的了解UINavigationController嗎?
UINavigationItem UINavigationBar 關(guān)系分析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末火邓,一起剝皮案震驚了整個濱河市铲咨,隨后出現(xiàn)的幾起案子鸣驱,更是在濱河造成了極大的恐慌蝠咆,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件再芋,死亡現(xiàn)場離奇詭異济赎,居然都是意外死亡司训,警方通過查閱死者的電腦和手機液南,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門统扳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咒钟,“玉大人若未,你說我怎么就攤上這事⊥蠊唬” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵甚淡,是天一觀的道長贯卦。 經(jīng)常有香客問我撵割,道長辙芍,這世上最難降的妖魔是什么羹与? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任纵搁,我火速辦了婚禮腾誉,結(jié)果婚禮上利职,老公的妹妹穿的比我還像新娘猪贪。我一直安慰自己哮伟,他們只是感情好楞黄,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布野宜。 她就那樣靜靜地躺著匾南,像睡著了一般馏锡。 火紅的嫁衣襯著肌膚如雪杯道。 梳的紋絲不亂的頭發(fā)上党巾,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天驳规,我揣著相機與錄音署海,去河邊找鬼。 笑死巩搏,一個胖子當著我的面吹牛贯底,可吹牛的內(nèi)容都是我干的禽捆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼琐凭,長吁一口氣:“原來是場噩夢啊……” “哼浊服!你這毒婦竟也來了牙躺?” 一聲冷哼從身側(cè)響起孽拷,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤膜宋,失蹤者是張志新(化名)和其女友劉穎秋茫,沒想到半個月后肛著,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年统抬,在試婚紗的時候發(fā)現(xiàn)自己被綠了火本。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片危队。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖钙畔,靈堂內(nèi)的尸體忽然破棺而出茫陆,到底是詐尸還是另有隱情,我是刑警寧澤擎析,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布簿盅,位于F島的核電站,受9級特大地震影響揍魂,放射性物質(zhì)發(fā)生泄漏桨醋。R本人自食惡果不足惜现斋,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一限书、第九天 我趴在偏房一處隱蔽的房頂上張望秉扑。 院中可真熱鬧秦躯,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間笨忌,已是汗流浹背途凫。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工犀盟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留迅耘,地道東北人纽哥。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容