02.自定义tabBar

02.自定义tabBar_第1张图片
最终效果

1.tabBar 的基本信息设置

1.1 tabBarItem 的信息设置

UIViewController *vc = [[UIViewController alloc] init];
    vc.tabBarItem.title = @"标题";
    vc.tabBarItem.image = [UIImage imageNamed:@"tabBar_new_icon"];
    vc.tabBarItem.selectedImage = [UIImage imageNamed:@"tabBar_new_click_icon"];
    vc.view.backgroundColor = [UIColor grayColor];

NSDictionary * attr = @{NSFont

AttributeName:[UIFont systemFontOfSize:12],NSForegroundColorAttributeName:[UIColor grayColor]};
    [vc.tabBarItem setTitleTextAttributes:attrs forState:UIControlStateNormal];
 NSDictionary * selectedAttrs = @{NSFontAttributeName:[UIFont systemFontOfSize:12],NSForegroundColorAttributeName:[UIColor darkGrayColor]};
    [vc.tabBarItem setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];

    [self addChildViewController:vc];

** 注意:**以上设置 tabBarItem 的 selectedImage 的方法,在实际运行过程中的效果与图片本身的效果会有很大差异-----系统会默认将选中图片渲染成蓝色展示

1.2 解决 tabBarItem 选中图片渲染的问题

  • 代码解决
    通过 UIImage的 imageWithRenderingMode 方法返回一个带有渲染模式的图片
- (UIImage *)imageWithRenderingMode:(UIImageRenderingMode)renderingMode ;

UIImageRenderingMode:
UIImageRenderingModeAutomatic  // 根据图片的使用环境和所处的绘图上下文自动调整渲染模式。  
UIImageRenderingModeAlwaysOriginal   // 始终绘制图片原始状态,不使用Tint Color。  
UIImageRenderingModeAlwaysTemplate   // 始终根据Tint Color绘制图片,忽略图片的颜色信息。  

UIImage *image = [UIImage imageNamed:imageName];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
vc.tabBarItem.selectedImage = image;

代码解决的缺陷:代码量繁琐,当图片用在另一个地方处理渲染效果时还需要再次设置

  • 一次性设置---推荐使用
02.自定义tabBar_第2张图片
设置图片渲染模式

1.3 appearance 设置文字属性

在1.1的代码中我们是通过下面方法,设置每一个item中文字的属性的。这种方法进行设置的话,需要对每一个item都进行设置,比较繁琐

- (void)setTitleTextAttributes:(nullable NSDictionary *)attributes forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
  • UIAppearance:通过UIAppearance设置一些UI的全局效果---实现一改全改的效果
// 通过appearance统一设置所有UITabBarItem的文字属性
// 后面带有UI_APPEARANCE_SELECTOR的方法, 都可以通过appearance对象来统一设置
 [[UITabBarItem appearance] setTitleTextAttributes:attrs forState:UIControlStateNormal];
 [[UITabBarItem appearance] setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];

2.自定义tabBar

2.1自定义控制器

创建继承于 UIViewController 的控制器----不再赘述

2.2自定义TabBarController

创建继承于 UITabBarController 的控制器

@interface ZZYTabBarViewController ()

@end

@implementation ZZYTabBarViewController

+ (void)initialize
{
    //1、设置UITabBarItem相关属性
    NSDictionary * attrs = @{NSForegroundColorAttributeName:[UIColor grayColor],NSFontAttributeName:[UIFont systemFontOfSize:12]};
    NSDictionary * selectedAttrs = @{NSForegroundColorAttributeName:[UIColor darkGrayColor],NSFontAttributeName:[UIFont systemFontOfSize:12]};
   
   UITabBarItem * item = [UITabBarItem appearance];
    [item setTitleTextAttributes:attrs forState:UIControlStateNormal];
    [item setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    //2、初始化子控制器
    [self setupChildVc:[[ZZYEssenceViewController alloc] init] title:@"精华" image:@"tabBar_essence_icon" selectedImage:@"tabBar_essence_click_icon"];
    
    [self setupChildVc:[[ZZYNewViewController alloc] init] title:@"新帖" image:@"tabBar_new_icon" selectedImage:@"tabBar_new_click_icon"];
    
    [self setupChildVc:[[ZZYFriendTrendsViewController alloc] init] title:@"关注" image:@"tabBar_friendTrends_icon" selectedImage:@"tabBar_friendTrends_click_icon"];
    
    [self setupChildVc:[[ZZYMeViewController alloc] init] title:@"我" image:@"tabBar_me_icon" selectedImage:@"tabBar_me_click_icon"];
    
    //3.自定义TabBar ----- 更换TabBar
    [self setValue:[[ZZYTabBar alloc]init] forKeyPath:@"tabBar"];
//    self.tabBar
}

- (void)setupChildVc:(UIViewController *)vc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
{
    // 设置文字和图片
    vc.tabBarItem.title = title;
    vc.tabBarItem.image = [UIImage imageNamed:image];
    vc.tabBarItem.selectedImage = [UIImage imageNamed:selectedImage];

    ZZYNavigationController * nav = [[ZZYNavigationController alloc]initWithRootViewController:vc];
    // 添加为子控制器
    [self addChildViewController:nav];

}

** 注意 :**

在设置自定义的 TabBar 时,由于 tabBar 是系统默认 只读属性,因此需要通过 KVC 语法,将自定义的 tabBar 对象,赋值给 tabBar 属性即可

- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
02.自定义tabBar_第3张图片
tabBar属性

2.3 自定义TabBar

创建继承于UITabBar 的 TabBar

#import "ZZYTabBar.h"

@interface ZZYTabBar()
/**
 *  发布按钮
 */
@property (nonatomic, weak) UIButton * publishButton;

@end

@implementation ZZYTabBar

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        
        UIButton *publishButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [publishButton setBackgroundImage:[UIImage imageNamed:@"tabBar_publish_icon"] forState:UIControlStateNormal];
        [publishButton setBackgroundImage:[UIImage imageNamed:@"tabBar_publish_click_icon"] forState:UIControlStateHighlighted];
        [self addSubview:publishButton];
        self.publishButton = publishButton;
        
    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    //设置发布按钮的frame
注意此处设置 frame 时直接获取 UIImage 对象宽高的方法
    self.publishButton.bounds = CGRectMake(0, 0, self.publishButton.currentBackgroundImage.size.width, self.publishButton.currentBackgroundImage.size.height);
    self.publishButton.center = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5);
    
    // 设置其他UITabBarButton的frame
    CGFloat buttonY = 0;
    CGFloat buttonW = self.frame.size.width / 5;
    CGFloat buttonH = self.frame.size.height;
    NSInteger index = 0;
    
    for (UIView * button in self.subviews) {
        if ([button isKindOfClass:NSClassFromString(@"UITabBarButton")])
        {
            //设置按钮的x值---注意此处自定义的按钮在中间,注意此处索引的处理
            CGFloat buttonX = buttonW * ((index > 1)?(index + 1):index);
            button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);
            
            // 增加索引
            index++;
        }

    }
}

** 封装控件基本步骤 **

  • 在 initWithFrame:方法中添加子控件,提供便利构造方法
  • 在 layoutSubviews 方法中设置子控件的 frame(一定要调用 super 的 layoutSubviews )
  • 增加模型属性,在模型属性 set 方法中设置数据到子控件上

2.4 对 Frame 进行封装

通过创建 UIView 的分类来方便对 view 的frame 中width height 属性的设置

#import 

@interface UIView (ZZYExtension)

@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;

//- (CGFloat)x;
//- (void)setX:(CGFloat)x;
/** 在分类中声明@property, 只会生成方法的声明, 不会生成方法的实现和带有_下划线的成员变量*/

@end

#import "UIView+ZZYExtension.h"

@implementation UIView (ZZYExtension)

- (void)setWidth:(CGFloat)width
{
    CGRect frame = self.frame;
    frame.size.width = width;
    self.frame = frame;
}

- (void)setHeight:(CGFloat)height{
    CGRect frame = self.frame;
    frame.size. height = height;
    self.frame = frame;
}


- (void)setX:(CGFloat)x
{
    CGRect frame = self.frame;
    frame.origin.x = x;
    self.frame = frame;
}

- (void)setY:(CGFloat)y
{
    CGRect frame = self.frame;
    frame.origin.y = y;
    self.frame = frame;
}

- (CGFloat)width
{
    return self.frame.size.width;
}

- (CGFloat)height
{
    return self.frame.size.height;
}

- (CGFloat)x
{
    return self.frame.origin.x;
}

- (CGFloat)y
{
    return self.frame.origin.y;
}
@end

封装后的按钮 frame 设置代码

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    CGFloat width = self.width;
    CGFloat height = self.height;
    
    //设置发布按钮的frame
    self.publishButton.width = self.publishButton.currentBackgroundImage.size.width;
    self.publishButton.height = self.publishButton.currentBackgroundImage.size.height;
    
    self.publishButton.center = CGPointMake(width * 0.5, height * 0.5);
    
    // 设置其他UITabBarButton的frame
    CGFloat buttonY = 0;
    CGFloat buttonW = width / 5;
    CGFloat buttonH = height;
    NSInteger index = 0;

     //下面的与上面重复
}

你可能感兴趣的:(02.自定义tabBar)