2.UINavigationController的backBarButtonItem嫁蛇、leftBarButtonItem

現(xiàn)象

在使用iOS導(dǎo)航欄時踩上的一些坑课幕,假設(shè)兩個UIViewController:A厦坛、B,B是A的子級視圖控制器

  1. 在B上自定義返回鍵backBarButtonItem無效及界面異常
  2. 修改所有UIViewController導(dǎo)航欄的按鈕

原因及解決方法

  1. 問題一:在B上自定義返回鍵backBarButtonItem無效及界面異常乍惊,可能原因解決方法如下:
  • 修改返回鍵標題無效杜秸,在A中設(shè)置了UIViewController的navigationItem.title,如下圖润绎,不設(shè)置時撬碟,該值默認是nil;如果該A先入棧莉撇,而后B入棧呢蛤,此時棧頂?shù)腂的返回鍵自動被設(shè)置為A的navigationItem.title的值,如果A的title為nil棍郎,則B的返回鍵會使用“Back”其障;
    navigationItem.title的描述

    backBarButtonItem設(shè)置的是下一級navigation的返回鍵
  • 重新定義返回鍵無效,如果要修改B中的backBarButtonItem涂佃,可以創(chuàng)建一個新的UIBarButtonItem來替換励翼,直接修改backBarButtonItem的title是無效的
    backBarButtonItem的描述

    推薦使用- (instancetype)initWithCustomView:(UIView *)customView;來自定義不同的樣子;但是如果只是想去掉backBarButtonItem辜荠,則可以使用一個空的UIBarButtonItem來替換
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleDone target:nil action:nil];

補充:如果不修改內(nèi)容汽抚,就是裝飾一下文本,可以使用setTitleTextAttributes:forState:

  • 重定義的返回鍵標題重疊侨拦,涉及到leftBarButtonItem殊橙,這個的使用場景有點像淘寶和微信的文章,使用在導(dǎo)航欄左側(cè)需要多個按鈕時,比如‘Back’膨蛮、‘Close’多個并列存在的情況叠纹,也可以用leftBarButtonItem來設(shè)置為一個返回鍵,但是需要設(shè)置backBarButtonItem為空或使用hidesBackButton隱藏 (2017.09.04修改)敞葛,不然會出現(xiàn)兩個標題重疊的情況誉察,leftBarButtonItem的設(shè)置方法參考backBarButtonItem的設(shè)置方法,還可以批量設(shè)置多個惹谐,使用leftBarButtonItems持偏。
    leftBarButtonItem和leftBarButtonItems
  1. 問題二:修改所有UIViewController導(dǎo)航欄的按鈕
    實際運用中,像導(dǎo)航欄這樣幾乎所有UIViewController都會用到的東西基本應(yīng)該在項目開始就準備后氨肌,如果要修改屬性鸿秆,秉持優(yōu)化代碼的精神,也應(yīng)該在一處修改怎囚,然后在所有其他地方都生效卿叽,因此,這里有兩種方法:
  • 繼承UIViewController重寫導(dǎo)航欄恳守,繼承UIViewController考婴,自定義一個導(dǎo)航欄,隱藏系統(tǒng)的導(dǎo)航欄催烘,然后在需要導(dǎo)航欄的地方用一句代碼實現(xiàn)創(chuàng)建導(dǎo)航欄沥阱。
    如我使用過的一個:QHBasicViewController(來源已不可考)
    QHBasicViewController.h
#import <UIKit/UIKit.h>

@interface QHBasicViewController : UIViewController

@property (nonatomic, strong) UILabel* navTitleLabel;///導(dǎo)航欄標題
@property (nonatomic, strong, readonly) UIView *navView;///導(dǎo)航欄,只讀
@property (nonatomic, strong) UIImageView* navBackgroundView;///導(dǎo)航欄背景
@property (nonatomic, strong, readonly) UIView* leftV;///導(dǎo)航欄左側(cè)View,只讀
@property (nonatomic, strong, readonly) UIView *rightV;///導(dǎo)航欄右側(cè)View伊群,只讀

/** 創(chuàng)建導(dǎo)航欄
 * @param szTitle 導(dǎo)航欄標題
 * @param menuItem block回調(diào)考杉,需要在這里定義導(dǎo)航欄上的各個按鈕
 */
- (void)createNavWithTitle:(NSString *)szTitle createMenuItem:(UIView *(^)(int nIndex))menuItem;

@end

QHBasicViewController.m

#import "QHBasicViewController.h"
#import "HHUtil.h"

#define StatusbarHeight ((isIos7 >= 7 && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1)?20.f:0.f)

#pragma mark - QHBasicViewController
@interface QHBasicViewController ()
{
}

@end

@implementation QHBasicViewController


- (void)viewWillAppear:(BOOL)animated
{
    //隱藏UIViewController的導(dǎo)航欄
    [[self navigationController] setNavigationBarHidden:YES];
    [super viewWillAppear:TRUE];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
}

- (void)createNavWithTitle:(NSString *)szTitle createMenuItem:(UIView *(^)(int nIndex))menuItem
{
    const CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
    const CGFloat navigationViewHeigth = 44.f;
    const CGFloat _nSpaceNavY = (isIos7 >= 7 && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1) ? 0 : 20;
    UIImageView *navIV = [[UIImageView alloc] initWithFrame:CGRectMake(0, _nSpaceNavY, screenWidth, 64 - _nSpaceNavY)];
    [navIV setImage:[UIImage imageNamed:@"bg_nav.png"]];
    _navBackgroundView = navIV;
    [self.view addSubview:navIV];
    
    /* { 導(dǎo)航條 } */
    _navView = [[UIImageView alloc] initWithFrame:CGRectMake(0.f, StatusbarHeight, screenWidth, navigationViewHeigth)];
    ((UIImageView *)_navView).backgroundColor = [UIColor clearColor];
    [self.view addSubview:_navView];
    _navView.userInteractionEnabled = YES;
    //
    if (szTitle != nil)
    {
        UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake((_navView.bounds.size.width - 240)/2, (_navView.bounds.size.height - 40)/2, 240, 40)];
        [titleLabel setText:szTitle];
        [titleLabel setTextAlignment:NSTextAlignmentCenter];
        [titleLabel setTextColor:[UIColor whiteColor]];
        [titleLabel setFont:[UIFont boldSystemFontOfSize:18]];
        [titleLabel setBackgroundColor:[UIColor clearColor]];
        titleLabel.numberOfLines = 2;
        _navTitleLabel = titleLabel;
        [_navView addSubview:_navTitleLabel];
    }
    //
    UIView *item1 = menuItem(0);
    if (item1 != nil)
    {
        _leftV = item1;
        [_navView addSubview:item1];
    }
    UIView *item2 = menuItem(1);
    if (item2 != nil)
    {
        _rightV = item2;
        [_navView addSubview:item2];
    }
}
@end

在創(chuàng)建你自己的UIViewController的時候,需要做的就是繼承QHBasicViewController而不是UIViewController舰始,然后在viewDidLoad的時候createNavWithTitle: createMenuItem:創(chuàng)建導(dǎo)航欄奔则,然后在塊回調(diào)中定義你自己的按鈕。

  • 繼承UINavigationController重寫push方法蔽午,繼承UINavigationController方法,重寫push方法酬蹋,在push前后統(tǒng)一修改backBarButtonItem及老、leftBarButtonItem和rightBarButtonItem,甚至其它的導(dǎo)航欄設(shè)置范抓,比如自定義titleView骄恶,導(dǎo)航欄背景之類的。
    奉上個人做的一個例子:
    HHNavigationController.h
#import <UIKit/UIKit.h>

@interface HHNavigationController : UINavigationController

/** 重載的initWithRootViewController:方法匕垫,附帶初始化導(dǎo)航欄
 * @param rootViewController 視圖控制器
 */
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController;

@end

HHNavigationController.m

#import "HHNavigationController.h"
#import <MediaPlayer/MediaPlayer.h>

@interface HHNavigationController ()<UIGestureRecognizerDelegate>

@property (nonatomic, strong) UIBarButtonItem *backBarButtonItm;

@end

@implementation HHNavigationController

- (instancetype)initWithRootViewController:(UIViewController *)rootViewController
{
    self = [super initWithRootViewController:rootViewController];
    if (self) {
        //設(shè)置導(dǎo)航欄和狀態(tài)欄字體顏色為白色僧鲁,導(dǎo)航欄背景設(shè)置為綠色
        rootViewController.navigationController.navigationBar.barTintColor = RGBA(129, 164, 128, 1);//導(dǎo)航欄為綠色
        rootViewController.navigationController.navigationBar.barStyle = UIBarStyleBlack;//狀態(tài)欄字體為白色
        rootViewController.navigationController.navigationBar.translucent = NO;//導(dǎo)航欄不透明
        //設(shè)置側(cè)滑滑動返回
        self.interactivePopGestureRecognizer.delegate = self;
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - action
-(void)onBack
{
    [self popViewControllerAnimated:YES];
}

#pragma mark - back button
-(UIBarButtonItem *)backBarButtonItm
{
    if (!_backBarButtonItm) {
        UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        backBtn.frame = CGRectMake(0, 0, 30, 30);
        [backBtn setImage:[UIImage imageNamed:@"btn_back"] forState:UIControlStateNormal];
        [backBtn addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside];
        UIBarButtonItem *backBarItm = [[UIBarButtonItem alloc] initWithCustomView:backBtn];
        _backBarButtonItm = backBarItm;
    }
    return _backBarButtonItm;
}

#pragma mark - Override
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    viewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:nil style:UIBarButtonItemStyleDone target:nil action:nil];//返回鍵置空
    [super pushViewController:viewController animated:animated];
    if (viewController.navigationItem.leftBarButtonItem == nil && [self.viewControllers count] > 1) {
        //設(shè)置返回鍵
        viewController.navigationItem.leftBarButtonItem = self.backBarButtonItm;
        //設(shè)置導(dǎo)航欄和狀態(tài)欄字體顏色為白色,導(dǎo)航欄背景設(shè)置為綠色
        viewController.navigationController.navigationBar.barTintColor = RGBA(129, 164, 128, 1);//導(dǎo)航欄為綠色
        viewController.navigationController.navigationBar.barStyle = UIBarStyleBlack;//狀態(tài)欄字體為白色
        viewController.navigationController.navigationBar.translucent = NO;//導(dǎo)航欄不透明
    }
}
@end

缺點

  • 原生的導(dǎo)航欄雖然方便,但是犧牲了很多便利寞秃,自定義起來比較麻煩斟叼,特別是如果要求動畫的話(這個需求很正常),基本就用不了只能自己寫一個偽導(dǎo)航欄來替代
  • 不容易統(tǒng)一春寿,如果使用present方法朗涩,呈現(xiàn)的方式都不同,也不會有導(dǎo)航欄绑改,雖然有方法加導(dǎo)航欄谢床,但是還是有差異,也容易給代碼的編寫造成困擾
  • 難定制厘线,遇到定制需求识腿,由于backBarButtonItem本身要求的在加載到bar之前設(shè)置好的限制,很難動態(tài)的變化

修改

2017.09.02 16:13 V1.0 Create
2017.09.04 09:36 V1.1 添加backBarButtonItem的隱藏方法介紹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末造壮,一起剝皮案震驚了整個濱河市渡讼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌费薄,老刑警劉巖硝全,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異楞抡,居然都是意外死亡伟众,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門召廷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凳厢,“玉大人,你說我怎么就攤上這事竞慢∠茸希” “怎么了?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵筹煮,是天一觀的道長遮精。 經(jīng)常有香客問我,道長败潦,這世上最難降的妖魔是什么本冲? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮劫扒,結(jié)果婚禮上檬洞,老公的妹妹穿的比我還像新娘。我一直安慰自己沟饥,他們只是感情好添怔,可當我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布湾戳。 她就那樣靜靜地躺著,像睡著了一般广料。 火紅的嫁衣襯著肌膚如雪砾脑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天性昭,我揣著相機與錄音拦止,去河邊找鬼。 笑死糜颠,一個胖子當著我的面吹牛汹族,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播其兴,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼顶瞒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了元旬?” 一聲冷哼從身側(cè)響起榴徐,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匀归,沒想到半個月后坑资,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡穆端,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年袱贮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片体啰。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡攒巍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出荒勇,到底是詐尸還是另有隱情柒莉,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布沽翔,位于F島的核電站兢孝,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏仅偎。R本人自食惡果不足惜西潘,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哨颂。 院中可真熱鬧,春花似錦相种、人聲如沸威恼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽箫措。三九已至腹备,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間斤蔓,已是汗流浹背植酥。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留弦牡,地道東北人友驮。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像驾锰,于是被迫代替她去往敵國和親卸留。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫椭豫、插件耻瑟、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,059評論 4 62
  • 1,Search Bar 怎樣去掉背景的顏色(storyboard里只能設(shè)置background顏色,可是發(fā)現(xiàn)cl...
    以德扶人閱讀 2,333評論 2 50
  • #iOS開發(fā)之UI篇#iOS開發(fā)之UI篇 #常用控件介紹1## #UI第09天:滾動視圖# ##UIScrollV...
    LennonLin閱讀 1,760評論 0 0
  • MVC 我們學(xué)習(xí)了koa處理url赏酥,Nunjucks渲染模塊喳整,但我們?nèi)ソY(jié)合著兩個的時候。當一個用戶請求URL裸扶,ko...
    _panda閱讀 1,404評論 0 0
  • 像迷路的南遷鳥兒 一心飛往溫暖的南方 沒有方向的旅行 還忘卻了路上的風(fēng)景 像在旅途發(fā)呆的鳥兒 任秋風(fēng)帶走思緒 剩下...
    路過且錯過閱讀 344評論 0 3