原文網址:http://blog.csdn.net/joonsheng/article/details/41362499
序
說到自定義UINavigetionController的返回按鈕,iOS7以后,多了一個“<” 這樣的返回圖標,而目前主流的應用,都是只保留了“<”,而去掉了文字,那么怎么樣自定義一個自己的“<"按鈕,或者用系統的“<”,但不要文字呢?
1.設置中的返回按鈕(帶文字)
2.音樂中播放時(不帶文字)
1、直接上答案
- //下面這兩句是讓系統的返回按鈕的文字為空,從而達到隱藏文字的作用
- UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];
- self.navigationItem.backBarButtonItem = backItem;
- //這句就是push了,所以在push前加上這樣一句,就保留了系統的自帶的“<",並且文字為空
- [self.navigationController pushViewController:registerVC animated:YES];
注:本文代碼,如果沒有說明,都是從A導航視圖push到B導航視圖時,在A導航視圖里設置的代碼。
看圖:
2、帶着問題看答案:
1、上面的方法,只是利用了系統的自帶"<", 有人可能就問,那如果我想自定義圖標呢?
- //下面兩行就是自定義,替換系統的“<"圖標
- 【1】 [self.navigationController.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]];
- [self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]];
- UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];
- self.navigationItem.backBarButtonItem = backItem;
這個方法,如果只是適配iOS 7以上,那么,是目前比較好的解決方案了。
特點:
1.實現了自定義圖標,可以沒有文字,
2.保存了iOS 7以上系統的pop手勢返回。
如果要適配iOS 6,那么就要判斷系統版本,如果大於iOS 7,就用上面的代碼,如果低於iOS 7.0,就用另外的代碼(下面在介紹)
效果如下圖:
backItem;
2、那么,我們在A視圖設置的代碼,系統是如何實現從A視圖push到B視圖后,顯示在B視圖的?
看圖:
顯示原理【2】:
1、如果B視圖有一個自定義的左側按鈕(leftBarButtonItem),則會顯示這個自定義按鈕;
2、如果B沒有自定義按鈕,但是A視圖的backBarButtonItem屬性有自定義項,則顯示這個自定義項;
3、如果前2條都沒有,則默認顯示一個后退按鈕,后退按鈕的標題是A視圖的標題。
3、如果理解了第2點,那么怎樣自定義代碼,才能適配iOS 6和iOS 7以上呢?
自定義要求:
1.自定義圖標,文字可要可不要。
2.對於iOS 7以上,保留pop手勢.
分析:如果在A視圖自定義了返回按鈕,又要適配iOS6 ,但由於iOS6 下沒有手勢返回,所以只能點擊左上角返回,怎么處理?
直接上答案:
方案一【3】:
在A視圖中:
- if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) //如果系統版本在iOS 7.0以上,執行
- {
- [self.navigationController.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"name="navibar_back_btn_bg_normal.png"]];
- [self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]];
- UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];
- self.navigationItem.backBarButtonItem = backItem;
- }
在B視圖中:
- if (SYSTEM_VERSION_LESS_THAN(@"7.0")) //如果系統版本在iOS 7.0以下(不包括7.0),執行
- {
- //導航條返回按鈕
- UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
- [button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png]forState:UIControlStateNormal];
- [button setFrame:CGRectMake(0,0,30,30)">];
- [button addTarget:self action:@selector(jumpBack:) forControlEvents:UIControlEventTouchUpInside];
- UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
- self.navigationItem.leftBarButtonItem = barButtonItem;
- }
- #pragma mark - 跳轉回去
- - (void)jumpBack:(id)sender{
- [self.navigationController popViewControllerAnimated:YES];
- }
方案二:
//在A視圖中:
- //開啟iOS7的滑動返回效果
- if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
- self.navigationController.interactivePopGestureRecognizer.delegate = nil;
- }
- [self.navigationController pushViewController:registerVC animated:YES];
//在B視圖中(ViewDidLoad):
- //導航條返回按鈕
- UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
- [button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png]forState:UIControlStateNormal];
- [button setFrame:CGRectMake(0,0,30,30)];
- [button addTarget:self action:@selector(jumpBack:) forControlEvents:UIControlEventTouchUpInside];
- UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
- self.navigationItem.leftBarButtonItem = barButtonItem;
- #pragma mark - 跳轉回去
- - (void)jumpBack:(id)sender{
- [self.navigationController popViewControllerAnimated:YES];
- }

方案三:
- - (void)viewWillAppear:(BOOL)animated
- {
- // 注意,這個<span style="font-family: Arial, Helvetica, sans-serif;">interactivePopGestureRecognizer</span><span style="font-family: Arial, Helvetica, sans-serif;">屬性是iOS 7才有的</span>
- self.navigationController.interactivePopGestureRecognizer.delegate = self;
- }
- //導航條返回按鈕
- UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
- [button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]
- forState:UIControlStateNormal];
- [button setFrame:CGRectMake(0,0,30,30)];
- [button addTarget:self action:@selector(jumpBack:) forControlEvents:UIControlEventTouchUpInside];
- UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
- self.navigationItem.leftBarButtonItem = barButtonItem;
- #pragma mark - 跳轉回去
- - (void)jumpBack:(id)sender{
- [self.navigationController popViewControllerAnimated:YES];
- }
- UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed: @"navibar_back_btn_bg_normal.png"] style:(UIBarButtonItemStylePlain) target:nil action:nil];
- self.navigationItem.backBarButtonItem = backItem;
看圖:
第二個"<",就是自定的圖片,這個自定義有意思嗎?大家看着用吧
2.自定義視圖無效!
- UIView * view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 30, 44)];
- view.backgroundColor = [UIColor colorWithRed:0.263 green:1.000 blue:0.311 alpha:1.000];
- UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithCustomView:view];
- self.navigationItem.backBarButtonItem = backItem;
3.自定義按鈕~
注意這個相對第1個自定義照片的區別:backBarButtonItem不能用View視圖方法自定義,而leftBarButtonItem可以哦!
- UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
- [button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"] forState:UIControlStateNormal];
- [button setFrame:CGRectMake(0, 0, 30, 44)];
- [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
- UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
- self.navigationItem.<span style="color:#ff0000;">leftBarButtonItem</span> = barButtonItem;
這個自定義,根據【2】,可以知道其作用,在這里不在多說。
4.pop手勢
- //官方文檔:
- NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationController : UIViewController
- @property(nonatomic, assign) id<UINavigationControllerDelegate> delegate;
- @property(nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer NS_AVAILABLE_IOS(7_0);
以上的方法,都是基於系統自帶的UINavigationController來自定義,如果不是系統的,比如淘寶的是自定義的UINavigation,所以沒有利用系統的pop手勢,而是自定義手勢。又比如天貓的只用到【2】的改變圖標,但文字都是統一的“返回”,並且部分頁面,不用pop手勢,直接彈回去。【分析於:2014.11.23日】
最后,大家都試試自定義自己的back按鈕吧!如果你有更多更好的自定義方法,記得分享哦!還有很多細節我沒有說到,如果大家感興趣的,可以自己在深入研究一下哦~
4、附錄:
【1】關於系統自帶的“<”圖標的官方解釋:
- /*
- The back indicator image is shown beside the back button.
- The back indicator transition mask image is used as a mask for content during push and pop transitions
- Note: These properties must both be set if you want to customize the back indicator image.
- */
- @property(nonatomic,retain) UIImage *backIndicatorImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;
- @property(nonatomic,retain) UIImage *backIndicatorTransitionMaskImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;
根據上面文檔:
1、只有這兩個屬性都設置了,才會顯示自定義的圖片。
2、這兩個屬性,只能用於iOS 7以上。
3、很多人問為什么要設置“backIndicatorTransitionMaskImage”這個屬性,看官方文檔就知道,當push、pop時顯示的是這張image,但是疑問的是,當我設置這張照片跟“backIndicatorImage”屬性的照片不一樣時,系統不管是push,還是pop,還是完成時,都只會顯示"backIndicatorImage"屬性設置的照片。但由於文檔沒有更多信息,所以,這個問題我也就沒有找到答案。
【2】參考一大神的總結:
UINavigationController Class Reference去,在“Updating the Navigation Bar”小節,有這么一段話:
The bar button item on the left side of the navigation bar allows for navigation back to the previous view controller on the navigation stack. The navigation controller updates the left side of the navigation bar as follows:
- If the new top-level view controller has a custom left bar button item, that item is displayed. To specify a custom left bar button item, set the leftBarButtonItem property of the view controller’s navigation item.
- If the top-level view controller does not have a custom left bar button item, but the navigation item of the previous view controller has a valid item in itsbackBarButtonItem property, the navigation bar displays that item.
- If a custom bar button item is not specified by either of the view controllers, a default back button is used and its title is set to the value of the title property of the previous view controller—that is, the view controller one level down on the stack. (If there is only one view controller on the navigation stack, no back button is displayed.)
我大致解釋一下,使用pushViewController切換到下一個視圖時,navigation controller按照以下3條順序更改導航欄的左側按鈕。
1、如果B視圖有一個自定義的左側按鈕(leftBarButtonItem),則會顯示這個自定義按鈕;
2、如果B沒有自定義按鈕,但是A視圖的backBarButtonItem屬性有自定義項,則顯示這個自定義項;
3、如果前2條都沒有,則默認顯示一個后退按鈕,后退按鈕的標題是A視圖的標題。
【3】關於判斷處理說明,和判斷系統版本代碼
- //檢查系統版本
- #define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
- #define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
- #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
- #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
- #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
官方文檔:
- + (UIDevice *)currentDevice;
- @property(nonatomic,readonly,retain) NSString *name; // e.g. "My iPhone"
- @property(nonatomic,readonly,retain) NSString *model; // e.g. @"iPhone", @"iPod touch"
- @property(nonatomic,readonly,retain) NSString *localizedModel; // localized version of model
- @property(nonatomic,readonly,retain) NSString *systemName; // e.g. @"iOS"
- @property(nonatomic,readonly,retain) NSString *systemVersion; // e.g. @"4.0"
- @property(nonatomic,readonly) UIDeviceOrientation orientation; // return current device orientation. this will return UIDeviceOrientationUnknown unless device orientation notifications are being generated.
- @property(nonatomic,readonly,retain) NSUUID *identifierForVendor NS_AVAILABLE_IOS(6_0); // a UUID that may be used to uniquely identify the device, same across apps from a single vendor.
nice~