zoukankan      html  css  js  c++  java
  • UITabBarController的使用

    UITabBarController的使用

    • 前言:
      苹果开发的小伙伴都知道,项目中只要用到了UITabBarController,UITabBarController就是APP的骨架。所以熟练掌握UITabBarController的使用方法才能编写出健壮的APP。

    在此介绍UITabBarController在项目中的实现的两种方式,一种使用系统自带的tabbar,一种使用自定义的tabbar。

    demo下载地址

    使用系统自带的tabbar

    UITabBarController由两部分组成,一个是UITabBarController包含的子视图,一个是tabbar。

    .h文件
    #import <UIKit/UIKit.h>
    @interface HSP_tabbar_VC : UITabBarController
    @end
    
    .m文件
    
    #import "HSP_tabbar_VC.h"
    #import "HHTabBar.h"
    #import "AppDelegate.h"
    
    #define isIPhoneX ScreenHeight==812
    
    @interface HSP_tabbar_VC ()
    
    @end
    
    #pragma - mark - 使用系统自带tabbar 的方式
    @implementation HSP_tabbar_VC
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        [self loadControllers];
    }
    
    - (void)loadControllers {
        //创建tabBarController
        UIViewController *vcA = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"firstVC"];
        UIViewController *vcB = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"secondVC"];
        UIViewController *vcC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"thiredVC"];
        UIViewController *vcD = [[UIViewController alloc]init];
        UIViewController *vcE = [[UIViewController alloc]init];
        UIViewController *vcF = [[UIViewController alloc]init];
        UIViewController *vcG = [[UIViewController alloc]init];
    
        
        UINavigationController *nav1 = [[UINavigationController alloc]initWithRootViewController:vcA];
        
        //添加控制器
        self.viewControllers = @[nav1,vcB,vcC,vcD,vcE,vcF,vcG];
        
        
        //设置tabBarButton
        nav1.tabBarItem = [[UITabBarItem alloc]initWithTitle:@"首页" image:[UIImage imageNamed:@"home_normal"] selectedImage:[UIImage imageNamed:@"home_highlight"]];
        vcB.tabBarItem = [[UITabBarItem alloc]initWithTitle:@"导览" image:[[UIImage imageNamed:@"topics_normal"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:@"topics_highlight"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
        vcC.tabBarItem = [[UITabBarItem alloc]initWithTitle:@"资讯" image:[UIImage imageNamed:@"service_normal"] selectedImage:[UIImage imageNamed:@"service_highlight"]];
        vcD.tabBarItem = [[UITabBarItem alloc]initWithTitle:@"资讯" image:[UIImage imageNamed:@"service_normal"] selectedImage:[UIImage imageNamed:@"service_highlight"]];
        vcE.tabBarItem = [[UITabBarItem alloc]initWithTitle:@"资讯" image:[UIImage imageNamed:@"service_normal"] selectedImage:[UIImage imageNamed:@"service_highlight"]];
        vcF.tabBarItem = [[UITabBarItem alloc]initWithTitle:@"资讯" image:[UIImage imageNamed:@"service_normal"] selectedImage:[UIImage imageNamed:@"service_highlight"]];
        vcG.tabBarItem = [[UITabBarItem alloc]initWithTitle:@"资讯" image:[UIImage imageNamed:@"service_normal"] selectedImage:[UIImage imageNamed:@"service_highlight"]];
        
        vcB.tabBarItem.imageInsets = UIEdgeInsetsMake(-20, 0, 0, 0);
        
        vcC.tabBarItem.badgeValue = @"2";
        vcC.tabBarItem.badgeColor = [UIColor redColor];
        
        self.tabBar.tintColor = [UIColor orangeColor];
        
        self.tabBar.backgroundColor = [UIColor redColor];
        self.tabBar.backgroundImage = [[UIImage alloc]init];
    }
    
    
    
    @end
    	
    

    以上使用系统自带tabbar应当注意的问题

    1. 为标签设置图片时,增加显示原图的方法,否则尺寸不对会出现图片显示不出来的情况。
    [[UIImage imageNamed:@"topics_normal"]
    imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] 
    
    2. 标签页是大图片时,设置imageInsets属性避免文字和图片重叠
    vcB.tabBarItem.imageInsets = UIEdgeInsetsMake(-20, 0, 0, 0);
    
    3. 通过设置背景图片去除系统自带的模糊效果
     self.tabBar.backgroundImage = [[UIImage alloc]init];
    

    自定义tabbar

    自定义tabbar的实现原理:将自定义的View 添加到系统的tabbar上,通过全局的 UITabBarController 类来完成UIViewController之间的切换。

    - (void)setSelectedIndex:(NSInteger)index {
    	for (HHTabBarItem *item in self.tabBarItems) {
    		if (item.tag == index) {
    			item.selected = YES;
    		} else {
    			item.selected = NO;
    		}
    	}
    	
        AppDelegate *dele = (AppDelegate *)[UIApplication sharedApplication].delegate;
    	UITabBarController *tabBarController = dele.tabVC;
    	if (tabBarController) {
    		tabBarController.selectedIndex = index;
    	}
    }
    

    对tabbar的封装分为两层,HHTabBar 以及 HHTabBarItem

    MacDown logo

    HHTabBar类的主要功能是为每个标签分配frame,然后通过接受HHTabBarItem类的点击事件(HHTabBarItem类继承自UIButton)来切换UIViewController。

    .h文件
    
    
    #import <UIKit/UIKit.h>
    #import "HHTabBarItem.h"
    #import "UIColor+HexColor.h"
    
    #define ScreenWidth [UIScreen mainScreen].bounds.size.width
    #define ScreenHeight [UIScreen mainScreen].bounds.size.height
    #define NewDefaultColor hexColorAlpha(@"#c77a3a", 1)
    
    
    
    
    @protocol LLTabBarDelegate <NSObject>
    
    - (void)tabBarDidSelectedRiseButton;
    
    @end
    
    @interface HHTabBar : UIView
    
    @property (nonatomic, copy) NSArray<NSDictionary *> *tabBarItemAttributes;
    @property (nonatomic, weak) id <LLTabBarDelegate> delegate;
    
    @end
    
    
    
    .m 文件
    
    #import "HHTabBar.h"
    #import "AppDelegate.h"
    
    @interface HHTabBar ()
    
    @property (strong, nonatomic) NSMutableArray *tabBarItems;
    
    @end
    
    @implementation HHTabBar
    
    #pragma mark - Lifecycle
    
    - (instancetype)initWithFrame:(CGRect)frame {
    	self = [super initWithFrame:frame];
    	
    	if (self) {
    		[self config];
    	}
    	
    	return self;
    }
    
    #pragma mark - Private Method
    
    - (void)config {
    	UIImageView *topLine = [[UIImageView alloc] initWithFrame:CGRectMake(0, -5, ScreenWidth, 5)];
    	topLine.image = [UIImage imageNamed:@"tapbar_top_line"];
    	[self addSubview:topLine];
    }
    
    - (void)setSelectedIndex:(NSInteger)index {
    	for (HHTabBarItem *item in self.tabBarItems) {
    		if (item.tag == index) {
    			item.selected = YES;
    		} else {
    			item.selected = NO;
    		}
    	}
    	
        AppDelegate *dele = (AppDelegate *)[UIApplication sharedApplication].delegate;
    	UITabBarController *tabBarController = dele.tabVC;
    	if (tabBarController) {
    		tabBarController.selectedIndex = index;
    	}
    }
    
    #pragma mark - Touch Event
    
    - (void)itemSelected:(HHTabBarItem *)sender {
        [self setSelectedIndex:sender.tag];
    }
    
    #pragma mark - Setter
    
    - (void)setTabBarItemAttributes:(NSArray<NSDictionary *> *)tabBarItemAttributes {
        _tabBarItemAttributes = tabBarItemAttributes.copy;
        
        CGFloat itemWidth = ScreenWidth / _tabBarItemAttributes.count;
        CGFloat tabBarHeight = CGRectGetHeight(self.frame);
        NSInteger itemTag = 0;
        BOOL passedRiseItem = NO;
        
        _tabBarItems = [NSMutableArray arrayWithCapacity:_tabBarItemAttributes.count];
        for (id item in _tabBarItemAttributes) {
            if ([item isKindOfClass:[NSDictionary class]]) {
                NSDictionary *itemDict = (NSDictionary *)item;
                
                HHTabBarItemType type = [itemDict[kHHTabBarItemAttributeType] integerValue];
                CGRect frame = CGRectMake(itemTag * itemWidth + (passedRiseItem ? itemWidth : 0), 0, itemWidth, tabBarHeight);
                
                HHTabBarItem *tabBarItem = [self tabBarItemWithFrame:frame
                                                               title:itemDict[kHHTabBarItemAttributeTitle]
                                                     normalImageName:itemDict[kHHTabBarItemAttributeNormalImageName]
                                                   selectedImageName:itemDict[kHHTabBarItemAttributeSelectedImageName] tabBarItemType:type];
                if (itemTag == 0) {
                    tabBarItem.selected = YES;
                    [tabBarItem setTitleColor:NewDefaultColor forState:UIControlStateSelected];
                }
                
                [tabBarItem addTarget:self action:@selector(itemSelected:) forControlEvents:UIControlEventTouchUpInside];
                
                tabBarItem.tag = itemTag;
                itemTag++;
    
                
                [_tabBarItems addObject:tabBarItem];
                [self addSubview:tabBarItem];
            }
        }
    }
    
    - (HHTabBarItem *)tabBarItemWithFrame:(CGRect)frame title:(NSString *)title normalImageName:(NSString *)normalImageName selectedImageName:(NSString *)selectedImageName tabBarItemType:(HHTabBarItemType)tabBarItemType {
        
        HHTabBarItem *item = [[HHTabBarItem alloc] initWithFrame:frame];
        [item setTitle:title forState:UIControlStateNormal];
        [item setTitle:title forState:UIControlStateSelected];
        item.titleLabel.font = [UIFont systemFontOfSize:10];
        UIImage *normalImage = [UIImage imageNamed:normalImageName];
        UIImage *selectedImage = [UIImage imageNamed:selectedImageName];
        [item setImage:normalImage forState:UIControlStateNormal];
        [item setImage:selectedImage forState:UIControlStateSelected];
        [item setTitleColor:[UIColor colorWithWhite:1 alpha:0.6] forState:UIControlStateNormal];
        [item setTitleColor:NewDefaultColor forState:UIControlStateSelected];
        item.tabBarItemType = tabBarItemType;
        
        return item;
    }
    
    
    @end
    

    HHTabBarItem类的功能是保持Label的位置不变,宽度随着文本信息的多少变化,同时图片保持与Label的距离恒定,这需要根据图片的大小计算imageView的中心点的位置。

    另外传递标签的文字和图片时用到的常量字符串也在HHTabBarItem类中定义。

    .h文件
    
    //
    
    #import <UIKit/UIKit.h>
    
    typedef NS_ENUM(NSUInteger, HHTabBarItemType) {
    	HHTabBarItemNormal = 0,
    	HHTabBarItemRise,
    };
    
    extern NSString *const kHHTabBarItemAttributeTitle ;// NSString
    extern NSString *const kHHTabBarItemAttributeNormalImageName;// NSString
    extern NSString *const kHHTabBarItemAttributeSelectedImageName;// NSString
    extern NSString *const kHHTabBarItemAttributeType;// NSNumber, HHTabBarItemType
    
    @interface HHTabBarItem : UIButton
    
    
    @end
    
    
    .m文件
    
    
    #import "HHTabBarItem.h"
    
    static float labelBottom = 3.0;
    static float imageLabelDis = 5.0;
    static float defaultLabelWidth = 18.0;
    
    NSString *const kHHTabBarItemAttributeTitle = @"HHTabBarItemAttributeTitle";
    NSString *const kHHTabBarItemAttributeNormalImageName = @"HHTabBarItemAttributeNormalImageName";
    NSString *const kHHTabBarItemAttributeSelectedImageName = @"HHTabBarItemAttributeSelectedImageName";
    NSString *const kHHTabBarItemAttributeType = @"HHTabBarItemAttributeType";
    
    @implementation HHTabBarItem
    
    - (instancetype)initWithFrame:(CGRect)frame {
    	self = [super initWithFrame:frame];
    	
    	if (self) {
    		[self config];
    	}
    	
    	return self;
    }
    
    - (instancetype)init {
    	self = [super init];
    	
    	if (self) {
    		[self config];
    	}
    	
    	return self;
    }
    
    - (instancetype)initWithCoder:(NSCoder *)aDecoder {
    	self = [super initWithCoder:aDecoder];
    	
    	if (self) {
    		[self config];
    	}
    	
    	return self;
    }
    
    - (void)config {
    	//self.adjustsImageWhenHighlighted = NO;  网上说有选择后出现灰色背景的情况,目前没有发现。
    	//self.imageView.contentMode = UIViewContentModeScaleAspectFit;
    }
    
    - (void)layoutSubviews {
    	[super layoutSubviews];
    	
    	[self.titleLabel sizeToFit];
    	CGSize titleSize = self.titleLabel.frame.size;
    
    	CGSize imageSize = [self imageForState:UIControlStateNormal].size;
    	if (imageSize.width != 0 && imageSize.height != 0) {
    		CGFloat imageViewCenterY = CGRectGetHeight(self.frame) - labelBottom - titleSize.height - imageSize.height / 2 - imageLabelDis;
    		self.imageView.center = CGPointMake(CGRectGetWidth(self.frame) / 2, imageViewCenterY);
    	} else {
    		CGPoint imageViewCenter = self.imageView.center;
    		imageViewCenter.x = CGRectGetWidth(self.frame) / 2;
    		imageViewCenter.y = (CGRectGetHeight(self.frame) - titleSize.height) / 2;
    		self.imageView.center = imageViewCenter;
    	}
    
    	CGPoint labelCenter = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) - labelBottom - titleSize.height / 2);
        self.titleLabel.frame = CGRectMake(0, 0, titleSize.width, defaultLabelWidth);
    	self.titleLabel.center = labelCenter;
    }
        
    // 还有一种实现方式是设置 Edge Insets,Xcode 7.0.1 好像有点不开心,在 IB 里面更改一下属性的时候,经常崩溃。。。
    /* 位置还有一点不准确,推荐用上面的代码来设置
     
     [self.titleLabel sizeToFit];
     CGSize titleSize = self.titleLabel.frame.size;
     CGSize imageSize = [self imageForState:UIControlStateNormal].size;
     NSInteger titleTopInset = CGRectGetHeight(self.frame) - 3 - titleSize.height;
     CGFloat titleRightInset = (CGRectGetWidth(self.frame) - titleSize.width) / 2 + titleSize.width;
     [self setTitleEdgeInsets:UIEdgeInsetsMake(titleTopInset, 0, 3, titleRightInset)];
     CGFloat imageViewLeftRightInset = (CGRectGetWidth(self.frame) - imageSize.width) / 2;
     [self setImageEdgeInsets:UIEdgeInsetsMake(CGRectGetHeight(self.frame) - 3 - 5 - titleSize.height - imageSize.height, imageViewLeftRightInset, 3 + 5 + titleSize.height, imageViewLeftRightInset)];
     
     */
    
    @end
    
    
  • 相关阅读:
    Java Web 开发必须掌握的三个技术:Token、Cookie、Session
    $.proxy和$.extend
    手机端和网页端使用同一后台时进行会话控制
    js中使用EL表达式总结
    Durandal入门
    RequireJs入门
    阿里云Prismplayer-Web播放器的使用
    Mac系统实现git命令自动补全
    Mac系统的终端显示git当前分支
    Gulp实现css、js、图片的压缩以及css、js文件的MD5命名
  • 原文地址:https://www.cnblogs.com/ceasar/p/8781788.html
Copyright © 2011-2022 走看看