UINavigation导航栏和UITabbar布局和样式

自定义UITabBarController


可以在ViewDidLoad里设置子控制器。当然其他地方也是可以的,但是放在这里可以更加有条理。


初始化


- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 添加所有的子控制器
    [self addAllChildVcs];
    
    // 创建自定义tabbar
    [self addCustomTabBar];
}


设置导航和tab标题

 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];




自定义UITabbar


自定义一个TabBar继承自UITabBar,然后在layoutSubviews里面设置子控件的frame


初始化设置可以放在initWithFrame中进行



设置选中tabBarItem 的tab bar上渲染的颜色(此图片奖显示在TabBarItem后面)

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];



自定义UINavigationController

设置主题

/**
 *  当第一次使用这个类的时候调用1次
 */
+ (void)initialize
{
    // 设置UINavigationBarTheme的主
    [self setupNavigationBarTheme];
    
    // 设置UIBarButtonItem的主题
    [self setupBarButtonItemTheme];
}


通过设置+ (instancetype)appearance;做统一的设置

设置UINavigationBar的主题

/**
 *  设置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的主题

/**
 *  设置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的样式只要重新自定义其属性就可以


统一处理所有和导航有关的push事件

在自定义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];
}




一种调整Tabbar外观的思路

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);






你可能感兴趣的:(UINavigation导航栏和UITabbar布局和样式)