(一)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;
通過對(duì)上述幾個(gè)類的屬性的羅列,我們可以做個(gè)總結(jié)
基本介紹
- UIBarItem
一個(gè)可以放置在Bar之上的所有小控件類的抽象類,可以設(shè)置標(biāo)題,圖片等 - UIBarButtonItem
繼承UIBarItem,增加了動(dòng)作以及目標(biāo)等button的屬性。相當(dāng)于放在UIToolBar或者UINavigationBar上的特殊的button。 - UINavigationItem
包含了title,prompt,titleView,leftBarButtonItem,rightBarButtonItem,backBarButonItem等當(dāng)前頁(yè)面上所有的信息 - UINavigationBar
NavigaitonBar就是導(dǎo)航欄 主要對(duì)UINavigationItem進(jìn)行棧管理 展示導(dǎo)航欄的外觀背景 - UINavigationController
包含了viewcontrollers、navigationbar、toolbar
關(guān)系綜述
- UINavigationController是一個(gè)容器類,對(duì)ViewController進(jìn)行棧管理,包含navigationBar。
- UINavigationBar 即UINavigationController頂部的導(dǎo)航欄,主要負(fù)責(zé)外觀背景的展示,并對(duì)navigationItem進(jìn)行棧管理
- UINavigationItem是導(dǎo)航欄上顯示的具體的元素的一個(gè)抽象類,UINavigationController 通過Category的方法為ViewController添加了一個(gè)navigationItem,把UINavigationItem交由ViewController管理
// Created on-demand so that a view controller may customize its navigation appearance.
這里引用葉落寒的一段介紹,更加的通俗易懂
通俗地說就是,UINavigationController是個(gè)容器,里面可以裝很多UIViewController。裝這么多UIViewController讓用戶怎么控制它們呢?總得有個(gè)工具吧,這個(gè)工具就是UINavigationBar。一個(gè)容器就這么一個(gè)bar,相當(dāng)于控制臺(tái)吧。但是管理那么多UIViewController,控制臺(tái)上得按鈕啊、標(biāo)題啊,都千篇一律是不是看起來太無聊了。為了解決這個(gè)問題,UINavigationController為每個(gè)UIViewController生成一個(gè)UINavigationItem,通過這個(gè)UINavigationItem可以改變控制臺(tái)“上面”的按鈕和標(biāo)題。如果你不自定義UINavigationItem,UINavigationController會(huì)使用默認(rèn)的;
(二)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è)置標(biāo)題的偏移量
- (void)setTitlePositionAdjustment:(UIOffset)adjustment forBarMetrics:(UIBarMetrics)barMetrics
- (nullable UIImage *)backButtonBackgroundImageForState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics
//設(shè)置返回按鈕標(biāo)題偏移量
- (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,//顯示加號(hào)
UIBarButtonSystemItemFlexibleSpace,//什么都不顯示,占位一個(gè)空間位置
UIBarButtonSystemItemFixedSpace,//和上一個(gè)類似
UIBarButtonSystemItemCompose,//顯示寫入按鈕
UIBarButtonSystemItemReply,//顯示循環(huán)按鈕
UIBarButtonSystemItemAction,//顯示活動(dòng)按鈕
UIBarButtonSystemItemOrganize,//顯示組合按鈕
UIBarButtonSystemItemBookmarks,//顯示圖書按鈕
UIBarButtonSystemItemSearch,//顯示查找按鈕
UIBarButtonSystemItemRefresh,//顯示刷新按鈕
UIBarButtonSystemItemStop,//顯示停止按鈕
UIBarButtonSystemItemCamera,//顯示相機(jī)按鈕
UIBarButtonSystemItemTrash,//顯示移除按鈕
UIBarButtonSystemItemPlay,//顯示播放按鈕
UIBarButtonSystemItemPause,//顯示暫停按鈕
UIBarButtonSystemItemRewind,//顯示退后按鈕
UIBarButtonSystemItemFastForward,//顯示前進(jìn)按鈕
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è)置導(dǎo)航欄中間的內(nèi)容標(biāo)題
@property(nullable, nonatomic,copy) NSString *title;
//設(shè)置導(dǎo)航欄中間的內(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同時(shí)顯示,其中l(wèi)eftBarButtonItem顯示在backBarButtonItem的右邊 默認(rèn)值為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 是一個(gè)NSString類型描述,注意添加該描述以后NavigationBar的高度會(huì)增加30,總的高度會(huì)變成74(不管當(dāng)前方向是Portrait還是Landscape,此模式下navgationbar都使用高度44加上prompt30的方式進(jìn)行顯示)。
如:
self.navigationItem.prompt=@"這是什么?";
self.title=@"HAH";
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會(huì)有一種模糊效果
@property(nonatomic,assign,getter=isTranslucent) BOOL translucent NS_AVAILABLE_IOS(3_0) UI_APPEARANCE_SELECTOR;
//UINavigationBar上面不只是簡(jiǎn)單的顯示標(biāo)題,它也將標(biāo)題進(jìn)行了堆棧的管理,每一個(gè)標(biāo)題抽象為的對(duì)象在iOS系統(tǒng)中是UINavigationItem對(duì)象,我們可以通過push與pop操作管理item組。
//向棧中添加一個(gè)item,上一個(gè)item會(huì)被推向?qū)Ш綑诘淖髠?cè),變?yōu)閜op按鈕,會(huì)有一個(gè)動(dòng)畫效果
- (void)pushNavigationItem:(UINavigationItem *)item animated:(BOOL)animated;
//pop一個(gè)item
- (nullable UINavigationItem *)popNavigationItemAnimated:(BOOL)animated;
//當(dāng)前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è)置導(dǎo)航欄的外觀
- (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;
//標(biāo)題的富文本
@property(nullable,nonatomic,copy) NSDictionary<NSString *,id> *titleTextAttributes NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
//標(biāo)題垂直偏移
- (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初始化,導(dǎo)航控制器的根控制器
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController;
//壓棧:將目標(biāo)控制器壓入棧中
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
//彈棧:將棧頂控制器從棧中彈出
- (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated;
//彈棧:彈到指定的目標(biāo)控制器
- (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
//彈棧:彈到根控制器
- (nullable NSArray<__kindof UIViewController *> *)popToRootViewControllerAnimated:(BOOL)animated;
//導(dǎo)航棧的棧頂視圖 只讀 就是某個(gè)導(dǎo)航棧的棧頂視圖,和導(dǎo)航息息相關(guān)
@property(nullable, nonatomic,readonly,strong) UIViewController *topViewController;
//當(dāng)前顯示的控制器 只讀 visibleViewController和哪個(gè)導(dǎo)航棧沒有關(guān)系,只是當(dāng)前顯示的控制器,也就是說任意一個(gè)導(dǎo)航的visibleViewController所返回的值應(yīng)該是一樣的
@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);
//是否隱藏導(dǎo)航欄
@property(nonatomic,getter=isNavigationBarHidden) BOOL navigationBarHidden;
//設(shè)置導(dǎo)航欄隱藏 是否有動(dòng)畫
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated;
//導(dǎo)航欄
@property(nonatomic,readonly) UINavigationBar *navigationBar;
//toolbar是否隱藏
@property(nonatomic,getter=isToolbarHidden) BOOL toolbarHidden NS_AVAILABLE_IOS(3_0);
//toolbar是否隱藏 是否有動(dòng)畫
- (void)setToolbarHidden:(BOOL)hidden animated:(BOOL)animated NS_AVAILABLE_IOS(3_0);
//toolbar對(duì)象
@property(null_resettable,nonatomic,readonly) UIToolbar *toolbar NS_AVAILABLE_IOS(3_0);
//委托
@property(nullable, nonatomic, weak) id<UINavigationControllerDelegate> delegate;
//邊緣側(cè)滑返回手勢(shì)
@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)時(shí)將導(dǎo)航欄隱藏 IOS8特性
@property (nonatomic, readwrite, assign) BOOL hidesBarsWhenKeyboardAppears NS_AVAILABLE_IOS(8_0);
//滾動(dòng)頁(yè)面時(shí)隱藏Bar IOS8特性
@property (nonatomic, readwrite, assign) BOOL hidesBarsOnSwipe NS_AVAILABLE_IOS(8_0);
//獲取能夠隱藏navigationBar的滑動(dòng)手勢(shì) 只讀
@property (nonatomic, readonly, strong) UIPanGestureRecognizer *barHideOnSwipeGestureRecognizer NS_AVAILABLE_IOS(8_0);
//當(dāng)設(shè)置為true時(shí),橫向方向時(shí)隱藏NavigationBar
@property (nonatomic, readwrite, assign) BOOL hidesBarsWhenVerticallyCompact NS_AVAILABLE_IOS(8_0);
//當(dāng)設(shè)置為true時(shí),如果有沒處理的點(diǎn)擊手勢(shì)就會(huì)隱藏和現(xiàn)實(shí)navigationBar
@property (nonatomic, readwrite, assign) BOOL hidesBarsOnTap NS_AVAILABLE_IOS(8_0);
//獲取能夠隱藏navigationBar的點(diǎn)擊手勢(shì) 只讀
@property (nonatomic, readonly, assign) UITapGestureRecognizer *barHideOnTapGestureRecognizer NS_AVAILABLE_IOS(8_0);
@end
@interface UIViewController (UINavigationControllerItem)
//導(dǎo)航欄上面用戶自定義視圖
@property(nonatomic,readonly,strong) UINavigationItem *navigationItem;
//推送時(shí)隱藏bottom
@property(nonatomic) BOOL hidesBottomBarWhenPushed;
//下級(jí)視圖的導(dǎo)航控制器
@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
(三)實(shí)際開發(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];
//是否半透明 當(dāng)為YES時(shí) 設(shè)置的導(dǎo)航欄背景顏色會(huì)和實(shí)際rgb值有誤差
self.navigationBar.translucent = NO;
//如果想要半透明效果 顏色沒有色差 可以通過設(shè)置背景圖片的方法 背景圖片會(huì)覆蓋barTintColor
//- (void)setBackgroundImage:(nullable UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics
}
2.UINavigationBar底部的shadowImage
Apple官方對(duì)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,否則無法實(shí)現(xiàn)效果
-(void)changeNavigationBarBottonLine {
//設(shè)置底部line顏色時(shí)需要同時(shí)設(shè)置backgroundImage即導(dǎo)航欄的背景圖片 否則沒有效果
[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.自定義導(dǎo)航欄的返回按鈕
@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 不支持對(duì)navigation items操作,所以此處對(duì)返回按鈕的操作是在ViewController完成的,以下代碼中self表示ViewController
Apple官方對(duì)setBackIndicatorImage和setBackIndicatorTransitionMaskImage做了如下解釋,必須同時(shí)設(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;
}
注意:
對(duì)backBarButtonItem的修改是在當(dāng)前viewController前一個(gè)頁(yè)面完成的,在當(dāng)前頁(yè)面修改針對(duì)下一個(gè)viewController的navigationItem生效
2.不顯示文字
設(shè)置Title在Y方向上的偏移量,使其移除屏幕,該方法在第一次進(jìn)入時(shí)會(huì)有個(gè)文字移動(dòng)的動(dòng)畫效果,效果不好,不推薦使用
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -100) forBarMetrics:UIBarMetricsDefault];
3.使用leftBarButtonItem替代backBarButtonItem
使用這種方法,不能使用邊緣滑動(dòng)返回手勢(shì),且不能同時(shí)設(shè)置圖片和標(biāo)題
-(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;
}
/**
* 導(dǎo)航條leftBarBtn事件
*/
- (void)clickLeftBarBtnItem:(UIBarButtonItem *)sender {
[self.navigationController popViewControllerAnimated:YES];
}
4.使用CustomView的方法
此方法不適于backBarButtonItem,只能用于leftBarButtonItem
注意:
1.如果B視圖有一個(gè)自定義的左側(cè)按鈕(leftBarButtonItem),則會(huì)顯示這個(gè)自定義按鈕;
2.如果B沒有自定義按鈕,但是A視圖的backBarButtonItem屬性有自定義項(xiàng),則顯示這個(gè)自定義項(xiàng);
3.如果前2條都沒有,則默認(rèn)顯示一個(gè)后退按鈕,后退按鈕的標(biāo)題是A視圖的標(biāo)題;
此處注意:
5.0中新增加了一個(gè)屬性leftItemsSupplementBackButton,通過指定該屬性為YES,可以讓leftBarButtonItem和backBarButtonItem同時(shí)顯示,其中l(wèi)eftBarButtonItem顯示在backBarButtonItem的右邊。
使用3、4方法,邊緣返回會(huì)失效,此時(shí)加上這句代碼依然可以實(shí)現(xiàn)邊緣滑動(dòng)返回
self.navigationController.interactivePopGestureRecognizer.delegate = self;
這里推薦使用FDFullscreenPopGesture 全屏滑動(dòng)手勢(shì)返回,減少工作量。
4.navigationBar偶爾顯示上一個(gè)頁(yè)面的navigationBar
一般情況下都是正常的。但是在偶然情況下,會(huì)出現(xiàn)在進(jìn)入新界面后,新界面的navigationBar會(huì)突然消失,出現(xiàn)的還是上一個(gè)界面的 navigationBar。從此以后,navigationBar 全亂了, kill 掉重新進(jìn),恢復(fù)正常。
原因:
一般我們會(huì)打點(diǎn)調(diào)用navigationBarHidden的屬性來設(shè)置導(dǎo)航欄是否隱藏,這種方法是不帶動(dòng)畫效果的。這樣偶爾就會(huì)導(dǎo)致錯(cuò)亂,這應(yīng)該是一個(gè)系統(tǒng)的bug,所以應(yīng)盡量使用
[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)測(cè)試只有在非rootViewController中才能生效,這樣在第一次進(jìn)入根視圖的時(shí)候navigationBar并不會(huì)變高,不知有沒有人知道該如何解決,歡迎賜教。
6.易混淆知識(shí)點(diǎn)
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.
- 如果當(dāng)前VC通過 self.navigationItem.titleView指定了自定義的titleView,系統(tǒng)將會(huì)顯示指定的titleView,設(shè)置self.title、self.navigationItem.title不會(huì)改變導(dǎo)航欄的標(biāo)題。
- 如果當(dāng)前VC沒有指定titleView,系統(tǒng)則會(huì)根據(jù)當(dāng)前VC的title或者當(dāng)前VC的navigationItem.title的內(nèi)容創(chuàng)建一個(gè)UILabel并顯示。
- self.title會(huì)重寫navigationItem和tabBarItem的title。
2.self.navigationItem,self.navigationController.navigationItem的關(guān)系
navigationItem是UIViewController的一個(gè)屬性,navigationController繼承UIViewController,自然會(huì)繼承viewControoler的navigationItem屬性。此處self.navigationController.navigationItem是應(yīng)該被忽視的。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在頂部,且他的背景擴(kuò)展到statusBar的區(qū)域
} NS_ENUM_AVAILABLE_IOS(7_0);
不正之處,還望多多指教!
參考文章
你真的了解UINavigationController嗎?
UINavigationItem UINavigationBar 關(guān)系分析