在ios中,系統(tǒng)提供的導(dǎo)航欄返回按鈕,會(huì)自動(dòng)包含許多其他我們可能用不到的View導(dǎo)致最后呈現(xiàn)的效果不如所愿,最常見(jiàn)的就是返回按鈕所占的位置太大了,比如這樣:

返回按鈕占位太大
因?yàn)閁IBarButtonItem是一個(gè)包裹嚴(yán)密的類(lèi),它將UIView包裹在他的內(nèi)部,使得我們沒(méi)辦法很方便地去獲取或者修改其中真正的Button(當(dāng)然我們可以用Runtime,KVC的方式來(lái)做,但我覺(jué)得還是稍顯麻煩).
因此我們通常都用自定義的方法來(lái)修改返回按鈕,但如果只是用[[UIBarButtonItem alloc] initWithCustomView:customBtn];來(lái)修改的話是無(wú)法使返回按鈕右邊的空隙減小的.
在系統(tǒng)的UIBarButtonSystemItem中有一個(gè)UIBarButtonSystemItemFixedSpace,它就是用來(lái)控制Item之間距離的,我們將它放在各個(gè)Item之間,并且將其width定為負(fù)數(shù),便可以使得Item之間的間隔縮小了,由于系統(tǒng)默認(rèn)的backItem距離最左邊還是有一些像素的間隔,如果需要縮短距離屏幕左邊的距離,那么就是按鈕的左右各需要一個(gè)UIBarButtonSystemItemFixedSpace,代碼如下
UIButton *leftBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[leftBtn setImage:[UIImage imageNamed:@"nav_back_icon"] forState:UIControlStateNormal];
[leftBtn addTarget:self action:@selector(backNavAction) forControlEvents:UIControlEventTouchUpInside];
leftBtn.frame = CGRectMake(-20, 0, 30, 30);
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithCustomView:leftBtn];
UIBarButtonItem *leftSpace1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
leftSpace1.width = -20;
UIBarButtonItem *leftSpace2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
leftSpace2.width = -20;
self.navigationItem.leftBarButtonItems = @[leftSpace1,leftItem,leftSpace2];
這樣,就達(dá)到我們想要的效果了:

調(diào)整后的返回按鈕
但是現(xiàn)在有一個(gè)新的問(wèn)題,我們的滑動(dòng)返回上級(jí)頁(yè)面的手勢(shì)沒(méi)了.在
UINavigationController的屬性中,我們可以找到一個(gè)手勢(shì)interactivePopGestureRecognizer,這個(gè)手勢(shì),就是我們滑動(dòng)返回的手勢(shì),打印這個(gè)代理self.navigationController.interactivePopGestureRecognizer.delegate得到結(jié)果:

默認(rèn)的滑動(dòng)返回手勢(shì)代理
我們可以通過(guò)將手勢(shì)的代理設(shè)置為控制器本身來(lái)重新激活滑動(dòng)返回手勢(shì):
self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;但是這又會(huì)帶來(lái)新的問(wèn)題,當(dāng)你返回上級(jí)頁(yè)面后(實(shí)際上還是同一個(gè)UINavigationController)會(huì)無(wú)法響應(yīng)所有的Action,所以你需要將代理重新還給原主人:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.oldNavGesDelegate = self.navigationController.interactivePopGestureRecognizer.delegate;
self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.navigationController.interactivePopGestureRecognizer.delegate = self.oldNavGesDelegate;
}
這樣我們就實(shí)現(xiàn)了既自定義返回按鈕,又保留了滑動(dòng)返回手勢(shì).