在iOS開(kāi)發(fā)過(guò)程中,導(dǎo)航欄是最為經(jīng)常用到的控件,處理不好總會(huì)出現(xiàn)一些瑕疵或者bug,寫(xiě)這篇文章旨在為自己記錄平時(shí)所用有關(guān)Navigation一些操作或者說(shuō)是小技巧。
下文涉及到的push邏輯都是從A頁(yè)面push到B頁(yè)面,我會(huì)直接以A、B介紹
一、關(guān)于返回Item
默認(rèn)從A—>B(push),B中返回按鈕的title顯示的是A的標(biāo)題,當(dāng)A的標(biāo)題過(guò)長(zhǎng),會(huì)顯示返回(back)。A標(biāo)題長(zhǎng)同時(shí)B標(biāo)題也長(zhǎng),就會(huì)出現(xiàn)B標(biāo)題被擠到右邊了,這就尷尬了。如下圖

網(wǎng)上有說(shuō)在A的viewWillDisappear將A的標(biāo)題設(shè)置成空的,在viewDidAppear方法中再將標(biāo)題設(shè)置原來(lái)的,但是這個(gè)在手勢(shì)側(cè)滑過(guò)程中顯示會(huì)有問(wèn)題,這里就不做演示了。
這里提供一個(gè)解決方案:讓A控制器繼承自BaseViewController(自己創(chuàng)建的控制器),在BaseViewController做以下操作:
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"返回"
style:UIBarButtonItemStyleDone
target:self
action:nil];
self.navigationItem.backBarButtonItem = backItem;
}

有時(shí)我們并不需要顯示title,在上圖中的“返回”設(shè)置成 nil 就可以解決問(wèn)題。當(dāng)然我們剛才并沒(méi)有改變返回的圖片都是用系統(tǒng)默認(rèn)的,如果只是單純的顯示自定義的返回圖標(biāo)(需求就是這么樣,有什么辦法),那么問(wèn)題來(lái)了,怎么設(shè)置比較合理。以
下給出幾種方案:
1、設(shè)置navigationItem的leftBarButtonItem(不推薦)
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"navigation_back"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(p_actionBack)];
self.navigationItem.leftBarButtonItem = backItem;

只是添加leftBarButtonItem側(cè)滑手勢(shì)被禁止了,圖標(biāo)離左側(cè)有一定距離,經(jīng)過(guò)如下修改:
- (void)p_addBackItem {
//間隙
UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:nil];
//spaceItem寬度為負(fù)值,相當(dāng)于左移
spaceItem.width = -8;
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"navigation_back"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(p_actionBack)];
self.navigationItem.leftBarButtonItems = @[spaceItem, backItem];
//設(shè)置代理,添加leftBarButtonItem系統(tǒng)的側(cè)滑手勢(shì)會(huì)被禁
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
- (void)p_actionBack {
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
return YES;
}

2、將title移出視圖外,從而達(dá)到隱藏的效果(推薦,作用范圍全局)
注意:這個(gè)需要在AppDelegate設(shè)置才有效
- (void)initBars {
UIImage *backImage = [UIImage imageNamed:@"navigation_back"];
UINavigationBar *navigationbar = [UINavigationBar appearance];
[navigationbar setBackIndicatorImage:backImage];
[navigationbar setBackIndicatorTransitionMaskImage:backImage];
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60)
forBarMetrics:UIBarMetricsDefault];
}


對(duì)比可以發(fā)現(xiàn),第一張圖是標(biāo)題比較短的時(shí)候顯示正常,第二張圖是標(biāo)題比較長(zhǎng)的時(shí)候標(biāo)題被往右擠了。

二、Navigation顯示或隱藏
項(xiàng)目中一般有一兩個(gè)頁(yè)面比較特殊,需要隱藏導(dǎo)航欄或者導(dǎo)航欄需要根據(jù)滑動(dòng)漸變,如登錄頁(yè)面需要隱藏導(dǎo)航欄。隱藏簡(jiǎn)單,拿起鍵盤(pán)就是干。
1、隱藏導(dǎo)航欄
使用[self.navigationController setNavigationBarHidden:NO animated:YES] 側(cè)滑手勢(shì)會(huì)被禁,所以需要加代理開(kāi)啟手勢(shì)
- (void)viewDidLoad {
[super viewDidLoad];
//設(shè)置代理
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//會(huì)導(dǎo)致側(cè)滑手勢(shì)被禁
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
//如果該控制器沒(méi)有上級(jí)控制器,建議將使用[self.navigationController setNavigationBarHidden:NO animated:animated] 效果會(huì)更好點(diǎn)
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
return YES;
}
2、導(dǎo)航欄漸變
介紹兩個(gè)方法:
//隱藏導(dǎo)航欄,但不隱藏上面的Item
[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init]
forBarMetrics:UIBarMetricsDefault];
//隱藏導(dǎo)航欄底部那條線
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
這個(gè)不做演示,推薦一個(gè)三方 LTNavigationBar
三、自定義TitleView
直接上代碼
UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
switchView.center = titleView.center;
[titleView addSubview:switchView];
self.navigationItem.titleView = titleView;
