02.自定义tabBar

作者: 断剑 | 来源:发表于2016-05-28 21:59 被阅读934次
    最终效果

    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;
    

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

    • 一次性设置---推荐使用
    设置图片渲染模式

    1.3 appearance 设置文字属性

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

    - (void)setTitleTextAttributes:(nullable NSDictionary<NSString *,id> *)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;
    
    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 <UIKit/UIKit.h>
    
    @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;
    
         //下面的与上面重复
    }
    

    相关文章

      网友评论

      • 40c6620494c9:还不传一波代码吗
        40c6620494c9:@断剑 1561003235@qq.com多谢咯。静等
        断剑:@偶像MJ 好久没整理了,你要是要的话,我找找给你发一个吧
        断剑:@偶像MJ 这个你直接复制就可以吧。。。。
      • 噜炉鲁鹿:代码在哪可以下载
        噜炉鲁鹿:@念男 传一个吧,我是新手,想下载学学
        断剑:@超超也想飞 暂时还没上传
      • maretell:有demo吗
        断剑:@maretell 暂时还没上传
      • 听小马儿说:MJ出品的
        断剑:@EowynQ 是的,MJ出品,必属精品

      本文标题:02.自定义tabBar

      本文链接:https://www.haomeiwen.com/subject/wsnwrttx.html