UINavigationBar
UINavigationBar- UINavigationController栈中的每一个viewController都对应一个UINavigationItem,用于修改当这个viewController作为栈顶控制器时的导航栏的内容
- UINavigationBar有一个栈(items)专门存储UINavigationController栈中的所有viewController的navigationItem属性
- UINavigationItem用于修改导航栏内容的API:
// 导航栏的内容由栈顶控制器的navigationItem属性决定
// 左上角的返回按钮
@property(nonatomic,retain) UIBarButtonItem *backBarButtonItem;
// 中间的标题视图
@property(nonatomic,retain) UIView *titleView;
// 中间的标题文字
@property(nonatomic,copy) NSString *title;
// 左上角的视图
@property(nonatomic,retain) UIBarButtonItem *leftBarButtonItem;UIBarButtonItem *rightBarButtonItem
// 右上角的视图
@property(nonatomic,retain) UIBarButtonItem *rightBarButtonItem;
- 如果同时设置了backButtonItem和leftButtonItem,从显示的优先级来讲(假如现在即将从A视图跳到B视图,从B视图角度说):
1、如果B视图有一个自定义的左侧按钮(leftBarButtonItem),则会显示这个自定义按钮;
2、如果B没有自定义按钮,但是A视图的backBarButtonItem属性有自定义项,则显示这个自定义项(依然是一个后退按钮,自定义的部分只有背景或title);
3、如果前2条都没有,则默认显示一个后退按钮,后退按钮的标题是A视图的标题,如果A视图标题太长则后退按钮的标题为"Back";
4.注意当前控制器的backBarButtonItem属性是针对后一个控制器的返回按钮,而不是当前控制前的返回按钮,比如此时的A控制器设置的backBarButtonItem属性是针对B控制器上的返回按钮的。另外,backBarButtonItem只能通过initWithTitle: style: target: action:方法初始化,也就意味着只能改返回按钮的标题等基本属性,无法高度自定义,如果想要有那种点击前后有特殊效果的,通过设置B控制器的leftBarButtonItem的方式实现(这个leftBarButtonItem需要绑定一个方法来调用popViewControllerAnimated:,从而实现返回功能)
5.通过重写pushViewController:animated:方法设置统一的返回按钮
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (self.childViewControllers.count > 0) {
/* 这里之所以要判断childViewControllers的count,是因为navigationController初始化的时候设置rootViewController时系统会自动调用push方法,
但是rootController的leftBarButtonItem我们是不需要设为返回按钮的,
所以要过滤掉,当super的push方法调用前,childViewControllers是不会加入viewController的,
所以rootViewController经过此方法时childViewControllers.count等于0 */
// 隐藏将要跳转到的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];
// 设置button的尺寸与内容一致
[backBtn sizeToFit];
[backBtn addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
// 设置整个button内容左对齐
backBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:backBtn];
// 之所以设置leftBarButtonItem而不用backBarButtonItem,是因为backBarButtonItem通过initWithCustomView:初始化不起作用
}
// 放在最后面的好处是,super的push方法调用时,也会调用将要跳转到的controller的viewDidLoad方法,如果有些需要跳转的controller需要自己的leftBarButtonItem时,就会替换掉之前自定义的返回按钮
[super pushViewController:viewController animated:animated];
}
6.通过apperance设置统一样式,要想通过此方式设置全局属性需要满足两个条件:
- 实现了UIApperance协议(UIView实现了该协议,而UITabBar,UINavigationBar都继承自UIView。除此之外UIBarButtonItem、UITabBarItem继承自已经实现了该协议的UIBarItem,注意UINavigationItem是继承自NSObject并且没有实现UIApperance协议)
- 带有UI_APPEARANCE_SELECTOR的方法或属性,才能进行全局的方式设置
+ (void)initialize {
// 设置navigationBar的统一背景
UINavigationBar *navigationBar = [UINavigationBar appearance];
[navigationBar setBackgroundImage:[UIImage imageNamed:@"navBar_background"] forBarMetrics:UIBarMetricsDefault];
}
UITabBar
UITabBar- 每个UITabBarController的childViewController都对应一个tabBar上的按钮(有多少个childViewController就有多少个这样的按钮),同时都有一个tabBarItem属性用于修改这个按钮的内容
- 注意设置tabBarItem的image属性时,image会被渲染成蓝色,要设置image的render永不被渲染
- 同UINavigationbar,UITabBar也可以通过appearance设置全局属性(所有的UITabBar都会被设置成一样的内容),同时也可以通过tabBarItem的apperace设置按钮的统一样式
UITabBarItem *item = [UITabBarItem appearance];
// 设置默认字体样式
NSMutableDictionary *attr = [[NSMutableDictionary alloc]init];
attr[NSFontAttributeName] = [UIFont systemFontOfSize:12];
attr[NSForegroundColorAttributeName] = [UIColor grayColor];
[item setTitleTextAttributes:attr forState:UIControlStateNormal];
// 设置选中字体样式,注意不要用上面的字典了,不同state下的属性要用不同的字典来装
NSMutableDictionary *attrSelected = [[NSMutableDictionary alloc]init];
attrSelected[NSFontAttributeName] = attr[NSFontAttributeName];
attrSelected[NSForegroundColorAttributeName] = [UIColor darkGrayColor];
[item setTitleTextAttributes:attrSelected forState:UIControlStateSelected];
- 因为tabBarItem无法设置按钮在tabBar上的位置,且UITabBarController的tabBar属性是只读的,只能通过自定义一个tabBar,在其内部通过layoutSubviews重新排布tabBar中按钮的位置,最后通过kvc用自定义tabBar替换系统自带的tabBar
[self setValue:tabBar forKeyPath:@"tabBar"];
网友评论