在ios中,系統提供的導航欄返回按鈕,會自動包含許多其他我們可能用不到的View導致最后呈現的效果不如所愿,最常見的就是返回按鈕所占的位置太大了,比如這樣:
返回按鈕占位太大
因為UIBarButtonItem是一個包裹嚴密的類,它將UIView包裹在他的內部,使得我們沒辦法很方便地去獲取或者修改其中真正的Button(當然我們可以用Runtime,KVC的方式來做,但我覺得還是稍顯麻煩).
因此我們通常都用自定義的方法來修改返回按鈕,但如果只是用[[UIBarButtonItem alloc] initWithCustomView:customBtn];
來修改的話是無法使返回按鈕右邊的空隙減小的.
在系統的UIBarButtonSystemItem
中有一個UIBarButtonSystemItemFixedSpace
,它就是用來控制Item之間距離的,我們將它放在各個Item之間,并且將其width定為負數,便可以使得Item之間的間隔縮小了,由于系統默認的backItem距離最左邊還是有一些像素的間隔,如果需要縮短距離屏幕左邊的距離,那么就是按鈕的左右各需要一個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];
這樣,就達到我們想要的效果了:
調整后的返回按鈕
但是現在有一個新的問題,我們的滑動返回上級頁面的手勢沒了.在
UINavigationController
的屬性中,我們可以找到一個手勢interactivePopGestureRecognizer
,這個手勢,就是我們滑動返回的手勢,打印這個代理self.navigationController.interactivePopGestureRecognizer.delegate
得到結果:
默認的滑動返回手勢代理
我們可以通過將手勢的代理設置為控制器本身來重新激活滑動返回手勢:
self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;
但是這又會帶來新的問題,當你返回上級頁面后(實際上還是同一個UINavigationController
)會無法響應所有的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;
}
這樣我們就實現了既自定義返回按鈕,又保留了滑動返回手勢.