UINavigationBar && UITabBar

UINavigationBar

UINavigationBar && UITabBar_第1张图片
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

UINavigationBar && UITabBar_第2张图片
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"];

你可能感兴趣的:(UINavigationBar && UITabBar)