在iOS開發過程中,導航欄是最為經常用到的控件,處理不好總會出現一些瑕疵或者bug,寫這篇文章旨在為自己記錄平時所用有關Navigation一些操作或者說是小技巧。
下文涉及到的push邏輯都是從A頁面push到B頁面,我會直接以A、B介紹
一、關于返回Item
默認從A—>B(push),B中返回按鈕的title顯示的是A的標題,當A的標題過長,會顯示返回(back)。A標題長同時B標題也長,就會出現B標題被擠到右邊了,這就尷尬了。如下圖
網上有說在A的viewWillDisappear將A的標題設置成空的,在viewDidAppear方法中再將標題設置原來的,但是這個在手勢側滑過程中顯示會有問題,這里就不做演示了。
這里提供一個解決方案:讓A控制器繼承自BaseViewController(自己創建的控制器),在BaseViewController做以下操作:
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"返回"
style:UIBarButtonItemStyleDone
target:self
action:nil];
self.navigationItem.backBarButtonItem = backItem;
}
有時我們并不需要顯示title,在上圖中的“返回”設置成 nil 就可以解決問題。當然我們剛才并沒有改變返回的圖片都是用系統默認的,如果只是單純的顯示自定義的返回圖標(需求就是這么樣,有什么辦法),那么問題來了,怎么設置比較合理。以
下給出幾種方案:
1、設置navigationItem的leftBarButtonItem(不推薦)
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"navigation_back"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(p_actionBack)];
self.navigationItem.leftBarButtonItem = backItem;
只是添加leftBarButtonItem側滑手勢被禁止了,圖標離左側有一定距離,經過如下修改:
- (void)p_addBackItem {
//間隙
UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:nil];
//spaceItem寬度為負值,相當于左移
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];
//設置代理,添加leftBarButtonItem系統的側滑手勢會被禁
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移出視圖外,從而達到隱藏的效果(推薦,作用范圍全局)
注意:這個需要在AppDelegate設置才有效
- (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];
}
對比可以發現,第一張圖是標題比較短的時候顯示正常,第二張圖是標題比較長的時候標題被往右擠了。
二、Navigation顯示或隱藏
項目中一般有一兩個頁面比較特殊,需要隱藏導航欄或者導航欄需要根據滑動漸變,如登錄頁面需要隱藏導航欄。隱藏簡單,拿起鍵盤就是干。
1、隱藏導航欄
使用[self.navigationController setNavigationBarHidden:NO animated:YES] 側滑手勢會被禁,所以需要加代理開啟手勢
- (void)viewDidLoad {
[super viewDidLoad];
//設置代理
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//會導致側滑手勢被禁
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
//如果該控制器沒有上級控制器,建議將使用[self.navigationController setNavigationBarHidden:NO animated:animated] 效果會更好點
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
return YES;
}
2、導航欄漸變
介紹兩個方法:
//隱藏導航欄,但不隱藏上面的Item
[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init]
forBarMetrics:UIBarMetricsDefault];
//隱藏導航欄底部那條線
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
這個不做演示,推薦一個三方 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;