UINavigationBar
UINavigationBar
- UINavigationController棧中的每一個(gè)viewController都對應(yīng)一個(gè)UINavigationItem,用于修改當(dāng)這個(gè)viewController作為棧頂控制器時(shí)的導(dǎo)航欄的內(nèi)容
- UINavigationBar有一個(gè)棧(items)專門存儲UINavigationController棧中的所有viewController的navigationItem屬性
- UINavigationItem用于修改導(dǎo)航欄內(nèi)容的API:
// 導(dǎo)航欄的內(nèi)容由棧頂控制器的navigationItem屬性決定
// 左上角的返回按鈕
@property(nonatomic,retain) UIBarButtonItem *backBarButtonItem;
// 中間的標(biāo)題視圖
@property(nonatomic,retain) UIView *titleView;
// 中間的標(biāo)題文字
@property(nonatomic,copy) NSString *title;
// 左上角的視圖
@property(nonatomic,retain) UIBarButtonItem *leftBarButtonItem;UIBarButtonItem *rightBarButtonItem
// 右上角的視圖
@property(nonatomic,retain) UIBarButtonItem *rightBarButtonItem;
- 如果同時(shí)設(shè)置了backButtonItem和leftButtonItem,從顯示的優(yōu)先級來講(假如現(xiàn)在即將從A視圖跳到B視圖,從B視圖角度說):
1、如果B視圖有一個(gè)自定義的左側(cè)按鈕(leftBarButtonItem),則會(huì)顯示這個(gè)自定義按鈕;
2、如果B沒有自定義按鈕,但是A視圖的backBarButtonItem屬性有自定義項(xiàng),則顯示這個(gè)自定義項(xiàng)(依然是一個(gè)后退按鈕,自定義的部分只有背景或title);
3、如果前2條都沒有,則默認(rèn)顯示一個(gè)后退按鈕,后退按鈕的標(biāo)題是A視圖的標(biāo)題,如果A視圖標(biāo)題太長則后退按鈕的標(biāo)題為"Back";
4.注意當(dāng)前控制器的backBarButtonItem屬性是針對后一個(gè)控制器的返回按鈕,而不是當(dāng)前控制前的返回按鈕,比如此時(shí)的A控制器設(shè)置的backBarButtonItem屬性是針對B控制器上的返回按鈕的。另外,backBarButtonItem只能通過initWithTitle: style: target: action:方法初始化,也就意味著只能改返回按鈕的標(biāo)題等基本屬性,無法高度自定義,如果想要有那種點(diǎn)擊前后有特殊效果的,通過設(shè)置B控制器的leftBarButtonItem的方式實(shí)現(xiàn)(這個(gè)leftBarButtonItem需要綁定一個(gè)方法來調(diào)用popViewControllerAnimated:,從而實(shí)現(xiàn)返回功能)
5.通過重寫pushViewController:animated:方法設(shè)置統(tǒng)一的返回按鈕
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (self.childViewControllers.count > 0) {
/* 這里之所以要判斷childViewControllers的count,是因?yàn)閚avigationController初始化的時(shí)候設(shè)置rootViewController時(shí)系統(tǒng)會(huì)自動(dòng)調(diào)用push方法,
但是rootController的leftBarButtonItem我們是不需要設(shè)為返回按鈕的,
所以要過濾掉,當(dāng)super的push方法調(diào)用前,childViewControllers是不會(huì)加入viewController的,
所以rootViewController經(jīng)過此方法時(shí)childViewControllers.count等于0 */
// 隱藏將要跳轉(zhuǎn)到的controller的UITabBar
viewController.hidesBottomBarWhenPushed = YES;
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[backBtn setImage:[UIImage imageNamed:@"navigationButtonReturn"] forState:UIControlStateNormal];
[backBtn setImage:[UIImage imageNamed:@"navigationButtonReturnClick"] forState:UIControlStateHighlighted];
[backBtn setTitle:@"返回" forState:UIControlStateNormal];
[backBtn.titleLabel setFont:[UIFont systemFontOfSize:16]];
[backBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[backBtn setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
// 設(shè)置button的尺寸與內(nèi)容一致
[backBtn sizeToFit];
[backBtn addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
// 設(shè)置整個(gè)button內(nèi)容左對齊
backBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:backBtn];
// 之所以設(shè)置leftBarButtonItem而不用backBarButtonItem,是因?yàn)閎ackBarButtonItem通過initWithCustomView:初始化不起作用
}
// 放在最后面的好處是,super的push方法調(diào)用時(shí),也會(huì)調(diào)用將要跳轉(zhuǎn)到的controller的viewDidLoad方法,如果有些需要跳轉(zhuǎn)的controller需要自己的leftBarButtonItem時(shí),就會(huì)替換掉之前自定義的返回按鈕
[super pushViewController:viewController animated:animated];
}
6.通過apperance設(shè)置統(tǒng)一樣式,要想通過此方式設(shè)置全局屬性需要滿足兩個(gè)條件:
- 實(shí)現(xiàn)了UIApperance協(xié)議(UIView實(shí)現(xiàn)了該協(xié)議,而UITabBar,UINavigationBar都繼承自UIView。除此之外UIBarButtonItem、UITabBarItem繼承自已經(jīng)實(shí)現(xiàn)了該協(xié)議的UIBarItem,注意UINavigationItem是繼承自NSObject并且沒有實(shí)現(xiàn)UIApperance協(xié)議)
- 帶有UI_APPEARANCE_SELECTOR的方法或?qū)傩裕拍苓M(jìn)行全局的方式設(shè)置
+ (void)initialize {
// 設(shè)置navigationBar的統(tǒng)一背景
UINavigationBar *navigationBar = [UINavigationBar appearance];
[navigationBar setBackgroundImage:[UIImage imageNamed:@"navBar_background"] forBarMetrics:UIBarMetricsDefault];
}
UITabBar
UITabBar
- 每個(gè)UITabBarController的childViewController都對應(yīng)一個(gè)tabBar上的按鈕(有多少個(gè)childViewController就有多少個(gè)這樣的按鈕),同時(shí)都有一個(gè)tabBarItem屬性用于修改這個(gè)按鈕的內(nèi)容
- 注意設(shè)置tabBarItem的image屬性時(shí),image會(huì)被渲染成藍(lán)色,要設(shè)置image的render永不被渲染
- 同UINavigationbar,UITabBar也可以通過appearance設(shè)置全局屬性(所有的UITabBar都會(huì)被設(shè)置成一樣的內(nèi)容),同時(shí)也可以通過tabBarItem的apperace設(shè)置按鈕的統(tǒng)一樣式
UITabBarItem *item = [UITabBarItem appearance];
// 設(shè)置默認(rèn)字體樣式
NSMutableDictionary *attr = [[NSMutableDictionary alloc]init];
attr[NSFontAttributeName] = [UIFont systemFontOfSize:12];
attr[NSForegroundColorAttributeName] = [UIColor grayColor];
[item setTitleTextAttributes:attr forState:UIControlStateNormal];
// 設(shè)置選中字體樣式,注意不要用上面的字典了,不同state下的屬性要用不同的字典來裝
NSMutableDictionary *attrSelected = [[NSMutableDictionary alloc]init];
attrSelected[NSFontAttributeName] = attr[NSFontAttributeName];
attrSelected[NSForegroundColorAttributeName] = [UIColor darkGrayColor];
[item setTitleTextAttributes:attrSelected forState:UIControlStateSelected];
- 因?yàn)閠abBarItem無法設(shè)置按鈕在tabBar上的位置,且UITabBarController的tabBar屬性是只讀的,只能通過自定義一個(gè)tabBar,在其內(nèi)部通過layoutSubviews重新排布tabBar中按鈕的位置,最后通過kvc用自定義tabBar替換系統(tǒng)自帶的tabBar
[self setValue:tabBar forKeyPath:@"tabBar"];