iOS设置自定义BackBarButtonItem

BackBarButtonItem 层级结构

首先我们看一下返回按钮的导航栏视图的结构层次,因为导航栏的视图加载以及初始化跟viewController的view不一样,不能再veiwDidLoad中去观察(viewWillAppear中也不行)要在viewDidLoad中才可以看到完整的导航栏视图结构层次。我们可以在一个有去掉文字的返回按钮控制器的viewDidApper中打上断点然后在控制台执行:

po [[UIWindow keyWindow] recursiveDescription]

打印结果:

<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>>

设置BackBarButtonItem

1.文字偏移法

#pragma mark - 自定义系统自带的backBarButtomItem
// 去掉系统默认自带的文字(上一个控制器的title),修改系统默认的样式(一个蓝色的左箭头)为自己的图片
-(void)customBackBarButtonItem {
// 去掉文字
// 自定义全局的barButtonItem外观
UIBarButtonItem *barButtonItemAppearance = [UIBarButtonItem appearance];
// 将文字减小并设其颜色为透明以隐藏
[barButtonItemAppearance setTitleTextAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:0.1], NSForegroundColorAttributeName: [UIColor clearColor]} forState:UIControlStateNormal];

// 设置图片
// 获取全局的navigationBar外观
UINavigationBar *navigationBarAppearance = [UINavigationBar appearance];
// 获取原图
UIImage *image = [[UIImage imageNamed:@"navigationbar_back"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
// 修改navigationBar上的返回按钮的图片,注意:这两个属性要同时设置
navigationBarAppearance.backIndicatorImage = image;
navigationBarAppearance.backIndicatorTransitionMaskImage = image;
}

缺点:打开相册等,系统自带的导航条右侧的取消按钮也是透明的,看不见了

2.文字透明法

- (void)setNaviBack{

UINavigationBar * navigationBar = [UINavigationBar appearance];

//返回按钮的箭头颜色

[navigationBar setTintColor:[UIColor colorWithRed:0.984 green:0.000 blue:0.235 alpha:1.000]];

//设置返回样式图片

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];

}

缺点:
1.导航条上的返回按钮 的 相应区域 还是原来那么大 没有变为图片的大小
2.第一个界面的 title 过长 会影响 跳转到的第二界面 的 title
因为没有去改变系统的backBarButtonItem,所以位置是没有变的。
3.设置 setBackButtonTitlePositionAdjustment还会导致一个问题,就是在做分享或者是支付,跳转其他APP(eg:支付宝,微信)之后,返回自己的APP的时候,会出现屏幕闪动的BUG,建议不要使用这个方法来做.

3.综合方案

以下代码写在自定义的导航控制器中
1.替换系统默认返回图片
- (void)viewDidLoad {
[super viewDidLoad];

self.delegate = self;

// 自定义返回图片(在返回按钮旁边) 这个效果由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;
}

// 去掉系统backBarButtonItem的默认显示效果
// 这个效果由控制器控制(A push B 则在A中设置)
/***
1、如果B视图有一个自定义的左侧按钮(leftBarButtonItem),则会显示这个自定义按钮;

2、如果B没有自定义按钮,但是A视图的backBarButtonItem属性有自定义项,则显示这个自定义项;

3、如果前2条都没有,则默认显示一个后退按钮,后退按钮的标题是A视图的标题。
*/
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:NULL];
viewController.navigationItem.backBarButtonItem = item;

[super pushViewController:viewController animated:animated];
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    X先生_未知数的X阅读 15,937评论 3 118
  • 寻寻觅觅,冷冷清清,凄凄惨惨戚戚。
    eb692fa556ec阅读 162评论 0 1
  • 2018年的1月过得真是心力交瘁,前半个月每日在浑浑噩噩后悔自责担心害怕中度过,开始是招聘的事情,接着是职称的事情...
    长青说说阅读 564评论 0 0
  • 我总也忘不了的那句话 在全世界我相信每个人都有一句也忘不了的一句话,我总也忘不了的那句话是在那...
    陈雲龙阅读 109评论 0 1
  • 青青云天 蒙蒙细雨 何带雨伞 携一书包直行 从小道 树木青翠 气色清新 下见小潭 登石堤 水中白荷舒展 羞涩打着朵...
    南方的候鸟阅读 331评论 0 3