美文网首页
UITabBarController 详解

UITabBarController 详解

作者: leonardni | 来源:发表于2017-10-18 15:41 被阅读237次

    一、 UITabBarController的原理


    1.1 基本概念

    父控制器:通过标签控制器管理多个子控制器,标签控制器就称为父控制器

    子控制器:添加到标签控制器里的控制器都做为标签控制器的子控制器

    标签栏:也叫选项卡栏,方便用户切换到对应的界面,当往标签控制器里添加子控制器,标签栏就会有序的自动生成对应的标签

    标签栏按钮:也叫标签,UITabBarButton,这个类只有apple内部开发人员才能使用

    1.2 UITabBarController原理

    1. 当UITabBarController做为Window的根控制器时,程序一启动,UITabBarController就会一次性初始化所有子控制器,但是默认只加载第一个控制器视图,其他视图控制器只初始化,但默认不会加载,只有在需要显示的时候才调用loadView方法加载。特殊情况:在AppDelegate中设置其他的子控制器视图的背景颜色,就会提前加载该控制器视图,但不显示该视图。

    2. 每一个控制器视图只加载一次,就会一直存在内存中,当切换子控制器时直接显示,不显示在屏幕上的子控制器不会被销毁。当遇到内存警告时,会释放掉没有加载的子控制器。

    3. 每个视图控制器都有一个tabBarController属性,通过它可以访问所在的UITabBarController,而且对于UITabBarController的直接子视图,其tabBarController属性相当于它的父视图parentViewController。

    4. 每个视图控制器都有一个tabBarItem属性,通过它控制视图在UITabBarController的tabBar中的显示信息

    5. tabBarItem的image属性必须是png格式(建议大小32*32),并且打开alpha通道否则无法正常显示。

    当往UITabBarController添加子控制器,标签栏就会有序的自动生成对应的UITabBarButton对象,有多少个子控制器,标签栏就有多少个UITabBarButton对象, 但是子控制器的数量超过5个的时候,标签栏上的第五个UITabBarButton对象就会显示成”More”类型的按钮

    二、UITabBarController的知识点


    2.1 关于UITabBarController

    1. UITabBarController没有根控制器的概念。在添加了相同的子控制器,不会增加tabitem的数量。子控器可以是UIViewController、UINavigationController、UITableViewController或者其他的视图控制器

    2. UITabBarButton在UITabBar中的位置是均分的,UITabBar的高度为49,UITabBarButton⾥面显⽰什么内容,由对应子控制器的tabBarItem属性来决定

    3. UITabBarController一般作为应用程序的rootViewController,但是它不能作为UINavigationController的根控制器

    4. UITabBarController默认只支持竖屏,当设备方向放生变化时候,它会查询viewControllers属性中包含的所有ViewController,仅当所有的viewController都支持该方向时,UITabBarController才会发生旋转,否则默认的竖向

    2.2 关于UITabBar

    2.2.1 简介

    UITabBar继承于UIView,方便用户切换到对应的界面,当往标签控制器里添加子控制器,标签栏就会有序的自动生成对应的标签;创建一个标签控制器,就默认创建一个标签栏,标签栏最多显示5个标签

    2.2.2 UITabBar常用的属性和方法

    // 代理
    @property(nonatomic,assign) id<UITabBarDelegate> delegate;
    // 设置数据模型,不能给系统默认创建的UITabBar设置items
    @property(nonatomic,copy) NSArray *items;
    // 设置选中数据模型,不能给系统默认创建的UITabBar设置selectedItem
    @property(nonatomic,assign) UITabBarItem *selectedItem;
    // iOS7之前,tintColor可以修改背景色
    @property(nonatomic,retain) UIColor *tintColor;
    // iOS7之后,修改背景色只能用barTintColor
    @property(nonatomic,retain) UIColor *barTintColor;
    // 设置UITabBar的背景图片
    @property(nonatomic,retain) UIImage *backgroundImage
    // 设置选中的按钮的背景图片
    @property(nonatomic,retain) UIImage *selectionIndicatorImage
    // 设置阴影图片,但必须设置backgroundImage属性
    @property(nonatomic,retain) UIImage *shadowImage
    // 设置数据模型,不能给系统默认创建的UITabBar设置items
    - (void)setItems:(NSArray *)items animated:(BOOL)animated;
    

    代理方法:

    // 选中时调用
    - (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item;
    // 即将编辑时调用
    - (void)tabBar:(UITabBar *)tabBar willBeginCustomizingItems:(NSArray *)items;  
    // 编辑时调用                  
    - (void)tabBar:(UITabBar *)tabBar didBeginCustomizingItems:(NSArray *)items; 
    // 即将结束编辑时调用        
    - (void)tabBar:(UITabBar *)tabBar willEndCustomizingItems:(NSArray *)items changed:(BOOL)changed; 
    // 结束编辑时调用
    - (void)tabBar:(UITabBar *)tabBar didEndCustomizingItems:(NSArray *)items changed:(BOOL)changed;
    

    2.2.3 UITabBarItem

    ----------  UITabBarItem的常用接口
    
    @interface UITabBarItem : UIBarItem
    
    // 设置选中图片
    @property(nonatomic,retain) UIImage *selectedImage;
    // 设置角标,一般用于提示用户有新消息
    @property(nonatomic,copy) NSString *badgeValue;
    // 初始化UITabBarItem对象
    - (instancetype)initWithTitle:(NSString *)title image:(UIImage *)image tag:(NSInteger)tag;
    // 初始化UITabBarItem对象
    - (instancetype)initWithTitle:(NSString *)title image:(UIImage *)image selectedImage:(UIImage *)selectedImage;
    // 初始化UITabBarItem对象
    - (instancetype)initWithTabBarSystemItem:(UITabBarSystemItem)systemItem tag:(NSInteger)tag;
    
    @end
    
    ----------  UIBarItem的常用接口
    
    @interface UIBarItem : NSObject
    
    // 是否有效
    @property(nonatomic,getter=isEnabled) BOOL enabled;
    // 设置标题
    @property(nonatomic,copy) NSString *title;
    // 设置图片
    @property(nonatomic,retain) UIImage *image;
    // 设置横向图片
    @property(nonatomic,retain) UIImage *landscapeImagePhone; 
    // 设置图片边距
    @property(nonatomic) UIEdgeInsets imageInsets;
    // 设置横向图片边距
    @property(nonatomic) UIEdgeInsets landscapeImagePhoneInsets;
    // 设置对应的控制器的标签
    @property(nonatomic) NSInteger tag;
    
    @end
    
    
    ----------  UITabBarSystemItem的枚举类型
    
    typedef NS_ENUM(NSInteger, UITabBarSystemItem) {
        UITabBarSystemItemMore,
        UITabBarSystemItemFavorites,
        UITabBarSystemItemFeatured,
        UITabBarSystemItemTopRated,
        UITabBarSystemItemRecents,
        UITabBarSystemItemContacts,
        UITabBarSystemItemHistory,
        UITabBarSystemItemBookmarks,
        UITabBarSystemItemSearch,
        UITabBarSystemItemDownloads,
        UITabBarSystemItemMostRecent,
        UITabBarSystemItemMostViewed,
    };
    

    2.2.4 覆盖UITabBarController自带的tabBar为自定义的tabBar操作原理

    tabBar上的按钮是在viewDidAppear的时候拿到 self.tabBar 再调用addSubViews添加上去的,在viewDidAppear之前把控制器的tabBar换成我们自己的tabBar,就会把tabBar上的按钮添加到自己的tabBar上。但是tabBar控制器的tabBar属性是只读的,不能直接赋值,可以利用运行时机制发送消息

    三、应用

    -(void)RTSetUpSubVcs{
        TGHomeViewController *HomeVC = [[TGHomeViewController alloc]init];
        HomeVC.view.backgroundColor = [UIColor whiteColor];
        BSENavigationController *HomeNav = [self ChildVC:HomeVC
                                               WithTitle:@"今托管"
                                                   image:@"tabbar_search"
                                           selectedImage:@"tabbar_search_sel"];
        
        TGRootChildrenViewController *childrenVC = [TGRootChildrenViewController new];
        BSENavigationController *childrenNav = [self ChildVC:childrenVC
                                                   WithTitle:@"小孩"
                                                       image:@"tabBar_children"
                                               selectedImage:@"tabBar_children_sel"];
        
        TGMineViewController *MyVC = [TGMineViewController new];
        BSENavigationController *MyNav = [self ChildVC:MyVC
                                             WithTitle:@"我的"
                                                 image:@"tabBar_mine"
                                         selectedImage:@"tabBar_mine_sel"];
        self.tabBar.barTintColor = [UIColor whiteColor];//tabbar 背景色
        self.tabBar.translucent = NO;//tarbar非透明
        
        self.viewControllers = @[HomeNav,childrenNav,MyNav];
    }
    
    
    #pragma mark  - 根TabBarController 添加子视图
    -(BSENavigationController *)ChildVC:(UIViewController *)VC WithTitle:(NSString *)title image:(NSString *)imagename selectedImage:(NSString *)selectedImageName
    {
        VC.title = title;
        UITabBarItem *barItem = [[UITabBarItem alloc]init];
        barItem.title = title;
        barItem.image = [[UIImage imageNamed:imagename]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        barItem.selectedImage = [[UIImage imageNamed:selectedImageName]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        [barItem setTitleTextAttributes:@{NSForegroundColorAttributeName: HEXCOLOR(0x666666)} forState:UIControlStateNormal];
        // 选中状态下的文字颜色
        [barItem setTitleTextAttributes:@{NSForegroundColorAttributeName: HEXCOLOR(kBlueGrayColor)} forState:UIControlStateSelected];
        BSENavigationController *Nav = [[BSENavigationController alloc]initWithRootViewController:VC];
        Nav.tabBarItem = barItem;
        return Nav;
    }
    

    四、遇到的问题


    1.之前初始化写错了添加子控制器的方法,设置了子控制的backgroundColor 导致 tabbarcontroller初始化所有子控制进入了didload方法。这样的直接坏处就是多数子控制器在didload里面都有网络请求方法,并且接口都有登录权限设置,如果初始化都直接加载,在用户登录成功后所有控制器又要在登录成功后,重新加载一次网络请求。浪费性能,同时也增加了程序的复杂度。

    相关文章

      网友评论

          本文标题:UITabBarController 详解

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