UINavigationBar && UITabBar

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"];
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在以前几个项目中都是多人开发,为避免在StoryBoard中代码修改很可能出现的问题,开发中几乎不用Story...
    灰溜溜的小王子阅读 2,239评论 2 3
  • 1,Search Bar 怎样去掉背景的颜色(storyboard里只能设置background颜色,可是发现cl...
    以德扶人阅读 2,466评论 2 50
  • 一:Xib复用 1.Xib简介 File's Owner是控制对象,可以说是nib文件的所有者,控制管理可视化对象...
    谢谢生活阅读 3,359评论 1 10
  • 成为你自己——这是电影《功夫熊猫3》里通篇都在表达的一个核心思想。 为了战胜重返凡间复仇的灵界天煞,阿宝带着拯救翡...
    落笔天涯2016阅读 567评论 2 3
  • 一座城市到底能有多叵测?牠 可以在一整天里头可以演绎四季 在白天和夜晚一样阴沉着脸,然后 北风撞在我怀里打滚耍赖 ...
    孙陆辰阅读 215评论 0 0