内容简介:前段时间,我们产品同学又提了个需求。咳咳,就是想要服务器动态控制tabBar的图片和文字,而且要兼容文字没有的情况下图片撑满,而且图片的显示范围固定。但是系统自带的tabBarItem我试了下是不能固定图片显示范围的,它是根据图片的大小来适应的。所有我就自定义了一套,最终效果如下(最后有demo地址):implementation:implementation:
前段时间,我们产品同学又提了个需求。咳咳,就是想要服务器动态控制tabBar的图片和文字,而且要兼容文字没有的情况下图片撑满,而且图片的显示范围固定。但是系统自带的tabBarItem我试了下是不能固定图片显示范围的,它是根据图片的大小来适应的。所有我就自定义了一套,最终效果如下(最后有demo地址):
1、自定义tabBarItem
@interface CYXTabBarItem : UIView /*未选中的图片*/ @property (nonatomic,strong) UIImage *image; /*选中的图片*/ @property (nonatomic,strong) UIImage *selectedImage; /*标题*/ @property (nonatomic,copy) NSString *title; /*是否是选中*/ @property (nonatomic,assign) BOOL selected; /*最大图片尺寸*/ @property (nonatomic,assign) CGSize maxImageSize; /*最小图片尺寸*/ @property (nonatomic,assign) CGSize minImageSize; /*文字颜色*/ @property (nonatomic,strong) UIColor *titleColor; /*选中的文字颜色*/ @property (nonatomic,strong) UIColor *selectedTitleColor; /*点击*/ @property (nonatomic,strong) void(^selectBlock)(void); /*更新布局方法 设置完之后记得调用*/ -(void)updateImageAndTitle; @end 复制代码
implementation:
@interface CYXTabBarItem() /*图片*/ @property (nonatomic,strong) UIImageView *imageView; /*文字*/ @property (nonatomic,strong) UILabel *titleLabel; @end @implementation CYXTabBarItem - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self addSubview:self.imageView]; [self addSubview:self.titleLabel]; [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(11); make.left.and.right.equalTo(self); make.top.equalTo(self).offset(35); }]; __weak __typeof(self) _self = self; [self setTapActionWithBlock:^{ if (_self.selectBlock) { _self.selectBlock(); } }]; } return self; } /*更新布局方法 设置完之后记得调用*/ -(void)updateImageAndTitle{ self.titleLabel.text = self.title; if (self.selected) { self.titleLabel.font = [UIFont systemFontOfSize:10.0]; self.titleLabel.textColor = self.selectedTitleColor; if (self.selectedImage) { self.imageView.image = self.selectedImage; } }else{ self.titleLabel.font = [UIFont boldSystemFontOfSize:10.0]; self.titleLabel.textColor = self.titleColor; if (self.image) { self.imageView.image = self.image; } } if ([self.title length]) { [self.imageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.height.and.width.mas_equalTo(22); make.centerX.equalTo(self); make.top.equalTo(self).offset(5); }]; }else{ [self.imageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.height.and.width.mas_equalTo(40); make.centerX.equalTo(self); make.top.equalTo(self).offset(5); }]; } } #pragma mark ---G -(UIImageView*)imageView{ if(!_imageView){ _imageView = [[UIImageView alloc] init]; } return _imageView; } -(UILabel*)titleLabel{ if(!_titleLabel){ _titleLabel = [[UILabel alloc] init]; _titleLabel.font = [UIFont systemFontOfSize:10]; _titleLabel.textColor = [UIColor grayColor]; _titleLabel.textAlignment = NSTextAlignmentCenter; } return _titleLabel; } 复制代码
2、自定义tabBarView
@interface CYXBarView : UIView /*初始化按钮*/ -(void)initButtonWithViewControllers:(NSArray<UIViewController *> * )viewControllers; /*最大图片尺寸*/ @property (nonatomic,assign) CGSize maxImageSize; /*最小图片尺寸*/ @property (nonatomic,assign) CGSize minImageSize; /*文字颜色*/ @property (nonatomic,strong) UIColor *titleColor; /*选中的文字颜色*/ @property (nonatomic,strong) UIColor *selectedTitleColor; /*点击*/ @property (nonatomic,strong) void(^selectBlock)(NSInteger index); @property (nonatomic, assign) NSInteger selectIndex; @end 复制代码
implementation:
@interface CYXBarView() @property (nonatomic,strong) NSMutableArray<CYXTabBarItem *> *items; @end @implementation CYXBarView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.maxImageSize = CGSizeMake(40, 40); self.minImageSize = CGSizeMake(20, 20); self.titleColor = [UIColor grayColor]; self.selectedTitleColor = [UIColor redColor]; self.items = [NSMutableArray new]; } return self; } -(void)initButtonWithViewControllers:(NSArray<UIViewController *> * )viewControllers{ [self.items removeAllObjects]; for (UIView * view in self.subviews) { [view removeFromSuperview]; } CGFloat itemWidth =screenWidth/viewControllers.count; for (int i= 0; i<viewControllers.count; i++) { CYXTabBarItem * item = [[CYXTabBarItem alloc] init]; item.maxImageSize = self.maxImageSize; item.minImageSize = self.minImageSize; item.titleColor = self.titleColor; item.selectedTitleColor = self.selectedTitleColor; UIViewController * viewController = viewControllers[i]; item.title = [viewController.tabBarItem.title length]?viewController.tabBarItem.title:viewController.title; item.selectedImage = viewController.tabBarItem.selectedImage; item.image = viewController.tabBarItem.image; [self addSubview:item]; [item mas_makeConstraints:^(MASConstraintMaker *make) { make.width.mas_equalTo(itemWidth); make.height.equalTo(self); make.top.equalTo(self); make.left.mas_equalTo(i*itemWidth); }]; [self.items addObject:item]; __weak __typeof(self) _self = self; item.selectBlock = ^{ _self.selectIndex = i; if (_self.selectBlock) { _self.selectBlock(_self.selectIndex); } }; [item updateImageAndTitle]; } self.selectIndex = 0; } - (void)setSelectIndex:(NSInteger)selectIndex { if (![self.items count]||selectIndex>=[self.items count]) {return;} // 先把上次选择的item设置为可用 CYXTabBarItem *lastItem = self.items[_selectIndex]; lastItem.selected = NO; // 再把这次选择的item设置为不可用 CYXTabBarItem *item = self.items[selectIndex]; item.selected = YES; _selectIndex = selectIndex; [lastItem updateImageAndTitle]; [item updateImageAndTitle]; } @end 复制代码
2、自定义tabBar
@class CYXBarView; @interface CYXTabBar : UITabBar @property (nonatomic,strong) CYXBarView *tabBarView; @end 复制代码
implementation:
@interface CYXTabBar () @end @implementation CYXTabBar - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self addSubview:self.tabBarView]; [self.tabBarView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.and.right.and.left.and.bottom.equalTo(self); }]; } return self; } - (void)layoutSubviews { [super layoutSubviews]; // 把tabBarView带到最前面,覆盖tabBar的内容 [self bringSubviewToFront:self.tabBarView]; /*隐藏原来的*/ for (UIView *view in self.subviews) { if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) { view.hidden = YES; } } } // 重写hitTest方法,让超出tabBar部分也能响应事件 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { if (self.clipsToBounds || self.hidden || (self.alpha == 0.f)) { return nil; } UIView *result = [super hitTest:point withEvent:event]; // 如果事件发生在tabbar里面直接返回 if (result) { return result; } // 这里遍历那些超出的部分就可以了,不过这么写比较通用。 for (UIView *subview in self.tabBarView.subviews) { // 把这个坐标从tabbar的坐标系转为subview的坐标系 CGPoint subPoint = [subview convertPoint:point fromView:self]; result = [subview hitTest:subPoint withEvent:event]; // 如果事件发生在subView里就返回 if (result) { return result; } } return nil; } #pragma mark ---G -(CYXBarView*)tabBarView{ if(!_tabBarView){ _tabBarView = [[CYXBarView alloc] init]; } return _tabBarView; } 复制代码
2、自定义UITabBarController
@interface CYXTabBarViewController : UITabBarController @end 复制代码
implementation:
@interface CYXTabBarViewController () @property (nonatomic,strong) CYXTabBar *customTabBar; @end @implementation CYXTabBarViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self setValue:self.customTabBar forKey:@"tabBar"]; [self initViewControllers]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.selectedIndex = 3; }); } -(void)initViewControllers{ NSMutableArray * viewControllers = [NSMutableArray new]; UIViewController *homeVC = [[UIViewController alloc] init]; homeVC.view.backgroundColor = [UIColor redColor]; [viewControllers addObject:[self addChildViewController:homeVC title:@"首页" imageNamed:@"tabBar_home"]]; UIViewController *expoVC = [[UIViewController alloc] init]; expoVC.view.backgroundColor = [UIColor yellowColor]; [viewControllers addObject:[self addChildViewController:expoVC title:@"家博会" imageNamed:@"tabBar_activity"]]; UIViewController *activityVC = [[UIViewController alloc] init]; activityVC.view.backgroundColor = [UIColor yellowColor]; [viewControllers addObject:[self addChildViewController:activityVC title:@"" imageNamed:@"tabBar_activity"]]; UIViewController *findVC = [[UIViewController alloc] init]; findVC.view.backgroundColor = [UIColor blueColor]; [viewControllers addObject:[self addChildViewController:findVC title:@"发现" imageNamed:@"tabBar_find"]]; UIViewController *mineVC = [[UIViewController alloc] init]; mineVC.view.backgroundColor = [UIColor greenColor]; [viewControllers addObject:[self addChildViewController:mineVC title:@"我的" imageNamed:@"tabBar_mine"]]; self.viewControllers = viewControllers; } // 添加某个 childViewController - (UINavigationController *)addChildViewController:(UIViewController *)vc title:(NSString *)title imageNamed:(NSString *)imageNamed { UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; // 如果同时有navigationbar 和 tabbar的时候最好分别设置它们的title vc.navigationItem.title = title; nav.tabBarItem.title = title; nav.tabBarItem.image = [UIImage imageNamed:imageNamed]; nav.tabBarItem.selectedImage = [UIImage imageNamed:@"jmtIconBg"]; return nav; } -(void)setViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers{ [super setViewControllers:viewControllers]; [self.customTabBar.tabBarView initButtonWithViewControllers:viewControllers]; } -(void)setSelectedIndex:(NSUInteger)selectedIndex{ [super setSelectedIndex:selectedIndex]; self.customTabBar.tabBarView.selectIndex = selectedIndex; } #pragma mark ---G -(CYXTabBar*)customTabBar{ if(!_customTabBar){ _customTabBar = [[CYXTabBar alloc] init]; __weak __typeof(self) _self = self; _customTabBar.tabBarView.selectBlock = ^(NSInteger index) { _self.selectedIndex = index; }; } return _customTabBar; } 复制代码
Appdelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = [[CYXTabBarViewController alloc] init]; // 设置这个窗口有主窗口并显示 [self.window makeKeyAndVisible]; return YES; } 复制代码
这样就实现上图所示效果图了,高度自定义化,可随意修改。欢迎讨论指教 demo: github.com/SionChen/CY…
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Android 自定义 View (04自定义属性)
- Vue自定义组件(简单实现一个自定义组件)
- Android 自定义View:深入理解自定义属性(七)
- Qt编写自定义控件20-自定义饼图 原 荐
- SpringBoot2 | SpringBoot自定义AutoConfiguration | SpringBoot自定义starter(五)
- 『互联网架构』软件架构-springboot自定义视图和自定义Starter(90)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。