可以在ViewDidLoad里设置子控制器。当然其他地方也是可以的,但是放在这里可以更加有条理。
- (void)viewDidLoad { [super viewDidLoad]; // 添加所有的子控制器 [self addAllChildVcs]; // 创建自定义tabbar [self addCustomTabBar]; }
childVc.tabBarItem.title = title; // tabbar标签上标签 childVc.navigationItem.title = title; // 导航栏上标签
childVc.tabBarItem.image = [UIImage imageWithName:imageName]; // 声明这张图片用原图(不要渲染) selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; childVc.tabBarItem.selectedImage = selectedImage;
// 设置tabBarItem的普通文字颜色 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[UITextAttributeTextColor] = [UIColor blackColor]; textAttrs[UITextAttributeFont] = [UIFont systemFontOfSize:10]; [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; // 设置tabBarItem的选中文字颜色 NSMutableDictionary *selectedTextAttrs = [NSMutableDictionary dictionary]; selectedTextAttrs[UITextAttributeTextColor] = [UIColor orangeColor]; [childVc.tabBarItem setTitleTextAttributes:selectedTextAttrs forState:UIControlStateSelected];
自定义一个TabBar继承自UITabBar,然后在layoutSubviews里面设置子控件的frame
初始化设置可以放在initWithFrame中进行
self.selectionIndicatorImage = [UIImage imageWithName:@"navigationbar_back_highlighted"];
self.backgroundImage = [UIImage imageWithName:@"tabbar_background"]
需要自定义布局tabbar时,可以改写
/** * 布局子控件 */ - (void)layoutSubviews { }
上面的UITabBar是自定义的,加上了一个UIButton
#import "HMTabBar.h" @interface HMTabBar() @property (nonatomic, weak) UIButton *plusButton; @end @implementation HMTabBar - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { if (!iOS7) { self.backgroundImage = [UIImage imageWithName:@"tabbar_background"]; } self.selectionIndicatorImage = [UIImage imageWithName:@"navigationbar_button_background"]; // 添加加号按钮 [self setupPlusButton]; } return self; } /** * 添加加号按钮 */ - (void)setupPlusButton { UIButton *plusButton = [[UIButton alloc] init]; // 设置背景 [plusButton setBackgroundImage:[UIImage imageWithName:@"tabbar_compose_button"] forState:UIControlStateNormal]; [plusButton setBackgroundImage:[UIImage imageWithName:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted]; // 设置图标 [plusButton setImage:[UIImage imageWithName:@"tabbar_compose_icon_add"] forState:UIControlStateNormal]; [plusButton setImage:[UIImage imageWithName:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted]; [plusButton addTarget:self action:@selector(plusClick) forControlEvents:UIControlEventTouchUpInside]; // 添加 [self addSubview:plusButton]; self.plusButton = plusButton; } - (void)plusClick { HMLog(@"plusClick----"); // 通知代理 if ([self.delegate respondsToSelector:@selector(tabBarDidClickedPlusButton:)]) { [self.delegate tabBarDidClickedPlusButton:self]; } } /** * 布局子控件 */ - (void)layoutSubviews { [super layoutSubviews]; // 设置plusButton的frame [self setupPlusButtonFrame]; // 设置所有tabbarButton的frame [self setupAllTabBarButtonsFrame]; } /** * 设置所有plusButton的frame */ - (void)setupPlusButtonFrame { self.plusButton.size = self.plusButton.currentBackgroundImage.size; self.plusButton.center = CGPointMake(self.width * 0.5, self.height * 0.5); } /** * 设置所有tabbarButton的frame */ - (void)setupAllTabBarButtonsFrame { int index = 0; // 遍历所有的button for (UIView *tabBarButton in self.subviews) { // 如果不是UITabBarButton, 直接跳过 if (![tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) continue; // 根据索引调整位置 [self setupTabBarButtonFrame:tabBarButton atIndex:index]; // 索引增加 index++; } } /** * 设置某个按钮的frame * * @param tabBarButton 需要设置的按钮 * @param index 按钮所在的索引 */ - (void)setupTabBarButtonFrame:(UIView *)tabBarButton atIndex:(int)index { // 计算button的尺寸 CGFloat buttonW = self.width / (self.items.count + 1); CGFloat buttonH = self.height; tabBarButton.width = buttonW; tabBarButton.height = buttonH; if (index >= 2) { tabBarButton.x = buttonW * (index + 1); } else { tabBarButton.x = buttonW * index; } tabBarButton.y = 0; } @end
设置TabBarItem
/** * 添加一个子控制器 * * @param childVc 子控制器对象 * @param title 标题 * @param imageName 图标 * @param selectedImageName 选中的图标 */ - (void)addOneChlildVc:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName { // 设置标题 childVc.title = title; // 设置图标 childVc.tabBarItem.image = [UIImage imageWithName:imageName]; // 设置tabBarItem的普通文字颜色 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[UITextAttributeTextColor] = [UIColor blackColor]; textAttrs[UITextAttributeFont] = [UIFont systemFontOfSize:10]; [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; // 设置tabBarItem的选中文字颜色 NSMutableDictionary *selectedTextAttrs = [NSMutableDictionary dictionary]; selectedTextAttrs[UITextAttributeTextColor] = [UIColor orangeColor]; [childVc.tabBarItem setTitleTextAttributes:selectedTextAttrs forState:UIControlStateSelected]; // 设置选中的图标 UIImage *selectedImage = [UIImage imageWithName:selectedImageName]; if (iOS7) { // 声明这张图片用原图(别渲染) selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; } childVc.tabBarItem.selectedImage = selectedImage; // 添加为tabbar控制器的子控制器 HMNavigationController *nav = [[HMNavigationController alloc] initWithRootViewController:childVc]; [self addChildViewController:nav]; }
需要重新调整子控件的布局时,调用setNeedsLayout方法,此方法会自动调用setFrame方法
[self.tabBar setNeedsLayout];
/** * 当第一次使用这个类的时候调用1次 */ + (void)initialize { // 设置UINavigationBarTheme的主 [self setupNavigationBarTheme]; // 设置UIBarButtonItem的主题 [self setupBarButtonItemTheme]; }
通过设置+ (instancetype)appearance;做统一的设置
/** * 设置UINavigationBarTheme的主题 */ + (void)setupNavigationBarTheme { UINavigationBar *appearance = [UINavigationBar appearance]; // 设置导航栏背景 if (!iOS7) { [appearance setBackgroundImage:[UIImage imageWithName:@"navigationbar_background"] forBarMetrics:UIBarMetricsDefault]; } // 设置文字属性 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[UITextAttributeTextColor] = [UIColor blackColor]; textAttrs[UITextAttributeFont] = [UIFont boldSystemFontOfSize:20]; // UIOffsetZero是结构体, 只要包装成NSValue对象, 才能放进字典\数组中,去除阴影效果 textAttrs[UITextAttributeTextShadowOffset] = [NSValue valueWithUIOffset:UIOffsetZero]; [appearance setTitleTextAttributes:textAttrs]; }
/** * 设置UIBarButtonItem的主题 */ + (void)setupBarButtonItemTheme { // 通过appearance对象能修改整个项目中所有UIBarButtonItem的样式 UIBarButtonItem *appearance = [UIBarButtonItem appearance]; /**设置文字属性**/ // 设置普通状态的文字属性 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[UITextAttributeTextColor] = [UIColor orangeColor]; textAttrs[UITextAttributeFont] = [UIFont systemFontOfSize:15]; textAttrs[UITextAttributeTextShadowOffset] = [NSValue valueWithUIOffset:UIOffsetZero]; [appearance setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; // 设置高亮状态的文字属性 NSMutableDictionary *highTextAttrs = [NSMutableDictionary dictionaryWithDictionary:textAttrs]; highTextAttrs[UITextAttributeTextColor] = [UIColor redColor]; [appearance setTitleTextAttributes:highTextAttrs forState:UIControlStateHighlighted]; // 设置不可用状态(disable)的文字属性 NSMutableDictionary *disableTextAttrs = [NSMutableDictionary dictionaryWithDictionary:textAttrs]; disableTextAttrs[UITextAttributeTextColor] = [UIColor lightGrayColor]; [appearance setTitleTextAttributes:disableTextAttrs forState:UIControlStateDisabled]; /**设置背景**/ // 技巧: 为了让某个按钮的背景消失, 可以设置一张完全透明的背景图片 [appearance setBackgroundImage:[UIImage imageWithName:@"navigationbar_button_background"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; }
如果需要更改后续UIBarButtonItem的样式只要重新自定义其属性就可以
在自定义UINavigationController中重写-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animate;方法
/** * 能拦截所有push进来的子控制器 */ - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { if (self.viewControllers.count > 0) { // 如果现在push的不是栈底控制器(最先push进来的那个控制器) viewController.hidesBottomBarWhenPushed = YES; // 设置导航栏按钮 viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithImageName:@"navigationbar_back" highImageName:@"navigationbar_back_highlighted" target:self action:@selector(back)]; viewController.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithImageName:@"navigationbar_more" highImageName:@"navigationbar_more_highlighted" target:self action:@selector(more)]; } [super pushViewController:viewController animated:animated]; }
UITabBar的样式和预期的不同,首先在viewDidLoad方法中输出self.view.subViews
-(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; NSLog(@"%@",self.tabBar.subViews); }
输出结果
(
"<_UITabBarBackgroundView: 0x7fc021df6590; frame = (0 0; 375 49); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fc02400a060>>",
"<UITabBarButton: 0x7fc021ddcaa0; frame = (2 1; 90 48); opaque = NO; layer = <CALayer: 0x7fc021e084e0>>",
"<UITabBarButton: 0x7fc021de4230; frame = (96 1; 90 48); opaque = NO; layer = <CALayer: 0x7fc021de4b40>>",
"<UITabBarButton: 0x7fc021deb780; frame = (190 1; 89 48); opaque = NO; layer = <CALayer: 0x7fc021e06340>>",
"<UITabBarButton: 0x7fc021e0ef50; frame = (283 1; 90 48); opaque = NO; layer = <CALayer: 0x7fc021de5f90>>",
"<UIImageView: 0x7fc02400b8f0; frame = (0 -0.5; 375 0.5); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fc02400b520>>"
)
但是UITabBarButton并不是公开的,所以查看其父类,是UIControl
继续遍历其subview,找到一个select有关的view将其从super中移除。可以用这个方法做一定的遍历,调整特定属性
-(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; for (UIView *child in self.tabBar.subviews) { NSLog(@"%@",child.superclass); NSLog(@"%@",child.subviews); for (UIView * childchild in child.subviews) { if([childchild isKindOfClass:[UILabel class]]){ UILabel *label=(UILabel *)childchild; label.font=[UIFont systemFontOfSize:15]; } } } NSLog(@"%@",self.tabBar.subviews); }
runtime机制
KVC修改readonly的属性
[self setValue:customTabBar forKeyPath:@"tabBar"];
NSLog(@"%p",customTabBar);