BackBarButtonItem 層級(jí)結(jié)構(gòu)
首先我們看一下返回按鈕的導(dǎo)航欄視圖的結(jié)構(gòu)層次,因?yàn)閷?dǎo)航欄的視圖加載以及初始化跟viewController的view不一樣,不能再veiwDidLoad中去觀察(viewWillAppear中也不行)要在viewDidLoad中才可以看到完整的導(dǎo)航欄視圖結(jié)構(gòu)層次。我們可以在一個(gè)有去掉文字的返回按鈕控制器的viewDidApper中打上斷點(diǎn)然后在控制臺(tái)執(zhí)行:
po [[UIWindow keyWindow] recursiveDescription]
打印結(jié)果:
<UIWindow: 0x7fc56e7051c0; frame = (0 0; 414 896); gestureRecognizers = <NSArray: 0x6000026ee580>; layer = <UIWindowLayer: 0x6000028ee320>>
| <UILayoutContainerView: 0x7fc56e705d80; frame = (0 0; 414 896); autoresize = W+H; gestureRecognizers = <NSArray: 0x6000026ef4e0>; layer = <CALayer: 0x6000028ee060>>
| | <UINavigationTransitionView: 0x7fc56e708270; frame = (0 0; 414 896); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x6000028eec60>>
| | | <UIViewControllerWrapperView: 0x7fc56e605850; frame = (0 0; 414 896); autoresize = W+H; layer = <CALayer: 0x6000028a5880>>
| | | | <UIView: 0x7fc56e50fa40; frame = (0 0; 414 896); autoresize = W+H; layer = <CALayer: 0x6000028abde0>>
| | | | | <UIButton: 0x7fc56e5039e0; frame = (172 230; 52 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x6000028abc80>>
| | | | | | <UIButtonLabel: 0x7fc56e603770; frame = (0.5 6; 51.5 18); text = 'GoNext'; alpha = 0.2; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x600000bd0690>>
| | <UINavigationBar: 0x7fc56e4107d0; frame = (0 44; 414 44); opaque = NO; autoresize = W; layer = <CALayer: 0x6000028c2ec0>>
| | | <_UIBarBackground: 0x7fc56e410a90; frame = (0 -44; 414 88); userInteractionEnabled = NO; layer = <CALayer: 0x6000028c2f20>>
| | | | <UIImageView: 0x7fc56e411620; frame = (0 88; 414 0.5); userInteractionEnabled = NO; layer = <CALayer: 0x6000028c2f60>>
| | | | <UIVisualEffectView: 0x7fc56e411850; frame = (0 0; 414 88); layer = <CALayer: 0x6000028c2f80>>
| | | | | <_UIVisualEffectBackdropView: 0x7fc56e706750; frame = (0 0; 414 88); autoresize = W+H; userInteractionEnabled = NO; layer = <UICABackdropLayer: 0x6000028ee9e0>>
| | | | | <_UIVisualEffectSubview: 0x7fc56e707810; frame = (0 0; 414 88); autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x6000028eec80>>
| | | <_UINavigationBarLargeTitleView: 0x7fc56e4125f0; frame = (0 0; 0 50); clipsToBounds = YES; hidden = YES; layer = <CALayer: 0x6000028c3140>>
| | | | <UILabel: 0x7fc56e4137b0; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x600000bcc9b0>>
| | | <_UINavigationBarContentView: 0x7fc56e411c80; frame = (0 0; 414 44); layer = <CALayer: 0x6000028c2fc0>>
| | | | <UILabel: 0x7fc56e503580; frame = (147.5 12; 119 20.5); text = 'ViewController'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x600000bc8c80>>
| | | <_UINavigationBarModernPromptView: 0x7fc56e608a20; frame = (0 0; 0 50); alpha = 0; hidden = YES; layer = <CALayer: 0x6000028a4840>>
設(shè)置BackBarButtonItem
1.文字偏移法
#pragma mark - 自定義系統(tǒng)自帶的backBarButtomItem
// 去掉系統(tǒng)默認(rèn)自帶的文字(上一個(gè)控制器的title),修改系統(tǒng)默認(rèn)的樣式(一個(gè)藍(lán)色的左箭頭)為自己的圖片
-(void)customBackBarButtonItem {
// 去掉文字
// 自定義全局的barButtonItem外觀
UIBarButtonItem *barButtonItemAppearance = [UIBarButtonItem appearance];
// 將文字減小并設(shè)其顏色為透明以隱藏
[barButtonItemAppearance setTitleTextAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:0.1], NSForegroundColorAttributeName: [UIColor clearColor]} forState:UIControlStateNormal];
// 設(shè)置圖片
// 獲取全局的navigationBar外觀
UINavigationBar *navigationBarAppearance = [UINavigationBar appearance];
// 獲取原圖
UIImage *image = [[UIImage imageNamed:@"navigationbar_back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
// 修改navigationBar上的返回按鈕的圖片,注意:這兩個(gè)屬性要同時(shí)設(shè)置
navigationBarAppearance.backIndicatorImage = image;
navigationBarAppearance.backIndicatorTransitionMaskImage = image;
}
缺點(diǎn):打開相冊(cè)等,系統(tǒng)自帶的導(dǎo)航條右側(cè)的取消按鈕也是透明的,看不見了
2.文字透明法
- (void)setNaviBack{
UINavigationBar * navigationBar = [UINavigationBar appearance];
//返回按鈕的箭頭顏色
[navigationBar setTintColor:[UIColor colorWithRed:0.984 green:0.000 blue:0.235 alpha:1.000]];
//設(shè)置返回樣式圖片
UIImage *image = [UIImage imageNamed:@"navi_back"];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
navigationBar.backIndicatorImage = image;
navigationBar.backIndicatorTransitionMaskImage = image;
UIBarButtonItem *buttonItem = [UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil];
UIOffset offset;
offset.horizontal = - 500;
offset.vertical = - 500;
[buttonItem setBackButtonTitlePositionAdjustment:offset forBarMetrics:UIBarMetricsDefault];
}
缺點(diǎn):
1.導(dǎo)航條上的返回按鈕 的 相應(yīng)區(qū)域 還是原來(lái)那么大 沒(méi)有變?yōu)閳D片的大小
2.第一個(gè)界面的 title 過(guò)長(zhǎng) 會(huì)影響 跳轉(zhuǎn)到的第二界面 的 title
因?yàn)闆](méi)有去改變系統(tǒng)的backBarButtonItem,所以位置是沒(méi)有變的。
3.設(shè)置 setBackButtonTitlePositionAdjustment還會(huì)導(dǎo)致一個(gè)問(wèn)題,就是在做分享或者是支付,跳轉(zhuǎn)其他APP(eg:支付寶,微信)之后,返回自己的APP的時(shí)候,會(huì)出現(xiàn)屏幕閃動(dòng)的BUG,建議不要使用這個(gè)方法來(lái)做.
3.綜合方案
以下代碼寫在自定義的導(dǎo)航控制器中
1.替換系統(tǒng)默認(rèn)返回圖片
- (void)viewDidLoad {
[super viewDidLoad];
self.delegate = self;
// 自定義返回圖片(在返回按鈕旁邊) 這個(gè)效果由navigationBar控制
[self.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"NavBack"]];
[self.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"NavBack"]];
}
2.去掉文字
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (self.viewControllers.count > 0) {
viewController.hidesBottomBarWhenPushed = YES;
}
// 去掉系統(tǒng)backBarButtonItem的默認(rèn)顯示效果
// 這個(gè)效果由控制器控制(A push B 則在A中設(shè)置)
/***
1、如果B視圖有一個(gè)自定義的左側(cè)按鈕(leftBarButtonItem),則會(huì)顯示這個(gè)自定義按鈕;
2、如果B沒(méi)有自定義按鈕,但是A視圖的backBarButtonItem屬性有自定義項(xiàng),則顯示這個(gè)自定義項(xiàng);
3、如果前2條都沒(méi)有,則默認(rèn)顯示一個(gè)后退按鈕,后退按鈕的標(biāo)題是A視圖的標(biāo)題。
*/
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:NULL];
viewController.navigationItem.backBarButtonItem = item;
[super pushViewController:viewController animated:animated];
}