ios tabbar插件_iOS之自定义tabBar

本文介绍了如何在iOS中自定义TabBar以满足更多功能需求。首先,通过系统样式创建TabBar并添加视图控制器,然后通过移除系统自带的TabBar控件,创建自定义的WJTabBar,并添加自定义按钮,设置点击事件和视图切换。自定义TabBar允许实现更复杂的样式和交互,如特殊按钮样式和中间按钮的定制。
摘要由CSDN通过智能技术生成

在iOS原生的tabBar中,能够实现按钮的点击事件,能够实现视图控制器的切换等,但是在实际工程中,对于tabBar的要求的功能往往是系统自己实现不了的,所以我们这里就需要用到自定义的tabBar了。

对于tabBar上展示视图控制器,我们会采用的是在把几个视图控制直接加载到tabBarController上去。这里新建三个视图控制器,由于在

一、系统样式

ViewController会有其他代码,所以我们这里另一写一个类,在这里只设置一个背景颜色就可以了。所以我们先新建一个类叫做WJViewController,让它继承自UIViewController。这里设置视图的背景颜色,这里可以设置为随机色。

// 设置背景颜色为随机色

self.view.backgroundColor = [UIColor colorWithRed:arc4random() % 256 /255.0 green:arc4random() % 256 /255.0 blue:arc4random() % 256 /255.0 alpha:1.0];

然后新建三个视图控制器,继承自WJViewController,这样三个视图控制的背景颜色都有了。新建的三个类,分别命名为WJFirstViewController、WJSecondViewController、WJThirdViewController。然后我们去实现相关方法。

1.首先创建一个tabBarController,用于接收实例化好的视图控制器。

// 1.创建标签栏控制器 UITabBarController *tabBarController = [[UITabBarController alloc]init];

2.然后就可创建需要让标签栏控制器管理的子视图控制器:

// 1>.第一个视图控制器

WJFirstViewController *first = [[WJFirstViewController alloc]init];

first.tabBarItem.title = @"first";

first.tabBarItem.image = [[UIImage imageNamed:@"tiaoman_u.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

first.tabBarItem.selectedImage = [[UIImage imageNamed:@"tiaoman_d.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

// 2>.第二个视图控制器

WJSecondViewController *second = [[WJSecondViewController alloc]init];

second.tabBarItem.title = @"second";

second.tabBarItem.image = [[UIImage imageNamed:@"faxian_u.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

second.tabBarItem.selectedImage = [[UIImage imageNamed:@"faxian_d.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

// 3>.第三个视图控制器

WJThirdViewController *third = [[WJThirdViewController alloc]init];

third.tabBarItem.title = @"third";

third.tabBarItem.image = [[UIImage imageNamed:@"wode_u.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

third.tabBarItem.selectedImage = [[UIImage imageNamed:@"wode_d.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

3.对子视图控制器进行管理

有两种方案可以选择:一是用数组进行接收,二是用一个方法进行接收子视图控制器。

法一:

//tabBarController.viewControllers = @[first, second, third];

法二:

[tabBarController addChildViewController:first];

[tabBarController addChildViewController:second];

[tabBarController addChildViewController:third];

这里最好使用第二种方法进行对子视图控制器进行管理。

代码进行到这里就可以把视图控制器tabBarController展示在Windows上了,所以需要把tabBarController设为根视图。

// 可以通过每个已经显示在界面上的视图,拿到当前应用程序的window

self.view.window.rootViewController = tabBarController;

}

这样代码进行到这里系统样式的功能就已经实现了,但是对于我们实际要求的功能相差甚远,所以我们开始自定义的tabBar的创建。

二、自定义样式

下面我们来简单分析下系统的tabBar的功能。

2.1分析

分析首先按钮有按钮点击事件,点击按钮后会改变相应的视图控制器,而且点击按钮后的图标会有相应的改变。而自定义的tabBar也需要达到这些功能,甚至还需要达到自定义按钮的形状的和功能的要求。

对于系统的tabBar来说,能够展示按钮的文字和图片,而这些内容是加载在tabBar的_UITabBarBackgroundView上的UITabBarButton上的UILabel和UIImageView上的。而我们要自定义按钮就需要覆盖系统本身的控件,但这些控件我们是拿不到的,用点语法这些控件是不能联想出来的,但我们又要实现和系统一样的功能,我们只能用一个方法把tabBar上的所有控件移除,因此要用遍历的方法实现移除;我们移除了系统自带的tabBar后就需要自定义一个wjTabBar来代替原有的tabBar。然后在wjTabBar上添加按钮,然后设置相应的点击事件,更改相应的状态就可实现和系统一样的功能。

// 声明一个wjTabBar的全局变量

@property (nonatomic, strong) WJTabBar *wj_tabBar;

- (void)viewDidAppear:(BOOL)animated {

[super viewDidAppear:animated];

// 2.删除自动创建的tabBarButton

for (UIView *view in self.tabBar.subviews) {

// 打印tabBar上所有控件

NSLog(@"%@",self.tabBar.subviews);

// 移除tabBar上所有的子控件

[view removeFromSuperview];

}

// 把self.wj_tabBar添加到视图上

[self.tabBar addSubview:self.wj_tabBar];

}

对wj_tabBar设置懒加载

#pragma mark - 懒加载

- (WJTabBar *)wj_tabBar {

if (!_wj_tabBar) {

// 创建wj_tabBar

_wj_tabBar = [[WJTabBar alloc]init];

// 设置frame

_wj_tabBar.frame = self.tabBar.bounds;

// 设置一个背景颜色

_wj_tabBar.backgroundColor = [UIColor cyanColor];

}

return _wj_tabBar;

}

2.2现在分析下按钮的创建:

按钮的创建应该视图控制器创建有关,所以在设计方法的时候应该传一个视图控制器的参数;按钮还应该设置文字,选中时的图片和普通状态下的图片。

2.2.1把tabBar展示到视图上

考虑到后期调用的方便,可以在.h文件中暴露出接口,以供使用;所以在.h文件中设置方法,然后在.m文件实现相关的方法。

#pragma mark - 添加子视图控制器

- (void)addController:(UIViewController *)controller withTitle:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName {

// 设置tabBarItem的子视图

controller.tabBarItem.title = title;

controller.tabBarItem.image = [[UIImage imageNamed:imageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

controller.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

// 将视图控制器添加到标签栏控制器中

[self addChildViewController:controller];

// 可以让自己定制的tabBar去创建一个对应的按钮

[self.wj_tabBar addButtonWithTabBarItem:controller.tabBarItem];

/* 测试的

static int i = 0;

if (i == 0) {

WJTabBarButton *button = [[WJTabBarButton alloc]initWithFrame:CGRectMake(10, 0, 45, 45)];

button.item = controller.tabBarItem;

button.normalColor = [UIColor blueColor];

button.selectedColor = [UIColor greenColor];

[button addTarget:self action:@selector(firstClick:)];

[self.wj_tabBar addSubview:button];

i = 1;

}

*/

}

然后去ViewControllers去添加视图控制器到tabBar上

#pragma mark - 创建视图控制器

- (void)wj_creatControll {

// 1.创建标签栏控制器

WJTabBarController *tabBarController = [[WJTabBarController alloc]init];

WJFirstViewController *first = [[WJFirstViewController alloc]init];

[tabBarController addController:first withTitle:@"first" imageName:@"tiaoman_u.png" selectedImageName:@"tiaoman_d.png"];

WJSecondViewController *second = [[WJSecondViewController alloc]init];

[tabBarController addController:second withTitle:@"second" imageName:@"faxian_u.png" selectedImageName:@"faxian_d.png"];

//WJThirdViewController *third = [[WJThirdViewController alloc]init];

//[tabBarController addController:third withTitle:@"third" imageName:@"wode_u.png" selectedImageName:@"wode_d.png"];

// 可以通过每个已经显示在界面上的视图,拿到当前应用程序的window

self.view.window.rootViewController = tabBarController;

// 设置第几个被选中

tabBarController.selectedIndex = 0;

// 这只centerView

UIButton *center = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 60, 60)];

[center setImage:[UIImage imageNamed:@"luffy1@2x.png"] forState:UIControlStateNormal];

tabBarController.centerView = center;

}

以上涉及到了WJTabBarButton这个类,这个类直接继承自UIView,在这个类中定义了几个属性:

2.2.2创建按钮

我们这里就可以去创建按钮了,首先去创建出按钮,然后去设计frame。

自定义的tabBar,我们就可以实现系统实现不了的样式,比如中间的按钮样式特别定制,比如像微博的tabBar中间的‘+’按钮。我们下面就实现实现下有特殊按钮的样式的tabBar。

#pragma mark - 当考虑有centerView的时候

- (void)setFrameWithCenter {

// 通用属性

CGFloat tabBarWidth = self.frame.size.width;

CGFloat tabBarHeight = self.frame.size.height;

NSInteger buttonCount = self.subviews.count;

if (self.centerView) {

// 有centerView的情况

buttonCount -= 1;

}

// centerView的相关属性

CGFloat centerWidth = self.centerView.frame.size.width;

CGFloat centerHeight = self.centerView.frame.size.height;

CGFloat centerX = (tabBarWidth - centerWidth) / 2.0f;

CGFloat centerY;

if (centerHeight <= tabBarHeight) {

centerY = (tabBarHeight - centerHeight) / 2.0f;

}

else {

centerY = tabBarHeight - centerHeight;

}

self.centerView.frame = CGRectMake(centerX, centerY, centerWidth, centerHeight);

// 按钮frame

CGFloat buttonY = 0;

CGFloat buttonHeight = self.frame.size.height;

CGFloat buttonWidth = (tabBarWidth - centerWidth) / buttonCount;

CGFloat buttonX;

int i = 0;

for (UIView *wjview in self.subviews) {

// 拿到按钮

if (wjview.tag != CenterTag) {

WJTabBarButton *button = (WJTabBarButton *)wjview;

// 计算frame

// 中间按钮之前的button

if (i < buttonCount / 2) {

buttonX = i * buttonWidth;

}

else {

// 中间按钮之后的button

buttonX = i * buttonWidth + centerWidth;

}

// 设置frame

button.frame = CGRectMake(buttonX, buttonY, buttonWidth, buttonHeight);

// 设置默认选中的按钮

if (i == self.selectedIndex) {

button.isSelected = YES;

}

// 设置tag值

button.tag = ButtonTag + i;

++i;

}

}

}

下面给centerView进行赋值

#pragma mark - centerView赋值

-(void)setCenterView:(UIView *)centerView {

_centerView = centerView;

UIView *view = (UIView *)[self viewWithTag:CenterTag];

if (view) {

// 移除之前的tag

[view removeFromSuperview];

}

else {

_centerView.tag = CenterTag;

// 显示在界面上

[self addSubview:_centerView];

}

}

但在外边调用的时候需要传一个中间按钮的方法,把中间按钮的一些属性传给上面的代码即:

#pragma mark - 外部给centerView赋值

-(void)setCenterView:(UIView *)centerView {

_centerView = centerView;

// 在tabBar上显示中间的视图

self.wj_tabBar.centerView = centerView;

}

最后在layoutSubView中实现以上的方法。

2.2.3创建按钮上的文字和图片

// 其实就是一个模型

@property (nonatomic, strong) UITabBarItem *item;

// ==================属性===============

// 按钮是否选中

@property (nonatomic, assign) BOOL isSelected;

// 按钮选中颜色

@property (nonatomic, strong) UIColor *selectedColor;

// 按钮普通状态颜色

@property (nonatomic, strong) UIColor *normalColor;

// 添加事件

- (void)addTarget:(id)target action:(SEL)action;

在.m文件中实现相关方法;

首先对一些属性设置默认值,这里可以提供两个初始化的方法,以便以后可以用frame的方法进行初始化和直接init方法进行初始化。

- (instancetype)initWithFrame:(CGRect)frame {

if (self = [super initWithFrame:frame]) {

// 设置属性默认值

// 选中状态的颜色

self.selectedColor = [UIColor redColor];

// 普通状态的颜色

self.normalColor = [UIColor lightGrayColor];

}

return self;

}

- (instancetype)init {

if (self = [super init]) {

// 设置属性默认值

self.selectedColor = [UIColor redColor];

self.normalColor = [UIColor lightGrayColor];

}

return self;

}

然后在按钮上去创建界面,

去创建子视图,这里只是单纯的创建子视图,而不去创建子视图的frame属性。这里去重写setter方法;

- (void)setItem:(UITabBarItem *)item {

_item = item;

// 移除按钮上原来的子视图

for (UIView *view in self.subviews) {

[view removeFromSuperview];

}

// 创建对应的子视图

// 1.图片

if (item.image || item.selectedImage) {

_imageView = [[UIImageView alloc]init];

[self addSubview:_imageView];

_imageView.image = item.image;

// 不缩放

[_imageView setContentMode:UIViewContentModeCenter];

}

// 2.文字

if (item.title) {

_textLabel = [[UILabel alloc] init];

[self addSubview:_textLabel];

_textLabel.text = item.title;

_textLabel.textAlignment = NSTextAlignmentCenter;

_textLabel.font = [UIFont systemFontOfSize:12.0];

}

}

下一步就去设置子视图的frame属性,让其在视图即将创建的时候去设置frame属性,因为在这个时候,tabBar上的按钮的个数已经全部创建完成,所以使用layoutSubviews方法设置frame属性,这里我们先封装一个方法去设置子视图的frame。在计算视图的frame的时候最好用相对位置,最好不要把位置写死了,万一以后要调整的话,一个参数更改,其他的参数位置也会跟着变化。

// 计算frame

- (void)setSubViewFrame {

// 通用

CGFloat buttonW = self.frame.size.width;

CGFloat buttonH = self.frame.size.height;

// 1.计算图片的frame

// 有图片

if (_imageView) {

CGFloat imageX = 0;

CGFloat imageY = 0;

CGFloat imageW = buttonW;

CGFloat imageH;

if (_textLabel) {

// 有文字

imageH = buttonH * 4 / 5.0f;

}

else {

// 没有文字

imageH = buttonH;

}

_imageView.frame = CGRectMake(imageX, imageY, imageW, imageH);

}

// 2.计算文字的frame

if (_textLabel) {

CGFloat textX = 0;

CGFloat textW = buttonW;

CGFloat textY;

CGFloat textH;

if (_imageView) {

// 有图片

textY = buttonH * 4 / 5.0f;

textH = buttonH / 5.0f;

}

else {

// 没有图片

textY = 0;

textH = buttonH;

}

_textLabel.frame = CGRectMake(textX, textY, textW, textH);

}

}

然后把以上的方法在layoutSubviews中去实现下就可以了。

这里可以设置最终文字所要展示的文字颜色:

// 设置最终所需属性

_textLabel.textColor = self.normalColor;

2.3添加按钮的点击事件:

#pragma mark - 按钮的点击事件

- (void)addTarget:(id)target action:(SEL)action {

_target = target;

_action = action;

}

#pragma mark - 添加事件

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

/*

// 在这里可以先测试下按钮的点击效果

if (self.isSelected) {

self.isSelected = NO;

}

else {

self.isSelected = YES;

}

*/

// 响应点击事件

if ([_target respondsToSelector:_action]) {

[_target performSelector:_action withObject:self];

}

}

按钮被点击后有选中的状态,之前的按钮就会失去被选中的状态,所以下面就去设置按钮的状态。

2.3.1按钮点击后改变选中状态

#pragma mark - 按钮点击

- (void)buttonOnClick:(WJTabBarButton *)button {

// 把其他的按钮变成非选中状态

// 获取到原来的按钮

WJTabBarButton *wjButton = (WJTabBarButton *)[self viewWithTag:self.selectedIndex + ButtonTag];

wjButton.isSelected = NO;

wjButton.userInteractionEnabled = YES;

// 把当前点击的按钮变成选中状态

button.isSelected = YES;

self.selectedIndex = button.tag - ButtonTag;

button.userInteractionEnabled = NO;

}

2.3.2按钮改变后更改颜色状态和文字

#pragma mark - 改变状态

- (void)setIsSelected:(BOOL)isSelected {

_isSelected = isSelected;

if (isSelected) {

// 被选中的时候,更改选中按钮的图片和选中时候颜色

self.imageView.image = self.item.selectedImage;

self.textLabel.textColor = self.selectedColor;

}

else {

// 失去选中的时候,按钮变成普通状态,颜色变成普通状态的颜色

self.imageView.image = self.item.image;

self.textLabel.textColor = self.normalColor;

}

}

2.4按钮点击后的视图控制器需要切换

分析:点击按钮视图切换,实质上是WJTabBar想要去切换视图控制器,但是他自己做不到,需要他人去帮他去做,这就要WJTabBarController去帮他实现视图的切换。我们可以用代理去实现点击按钮实现视图的切换。

那要实现代理,实在什么地方呢?答案是在选中的下标的set方法去实现,所以我们这里需要对选中下标的setter方法进行重写。

2.4.1对代理进行简单的分析:

代理的三要素:协议、代理、委托。这里的协议就是要切换到指定的视图控制器;代理就是WJTabBarController;委托就是WJTbaBar。

(1)代理方

首先在代理的.h文件去声明指定的协议

// 指定协议

@protocol WJTabBarDelegate

然后需要一个代理,这相当于是对代理名的重写

// 需要一个代理

@property (nonatomic, weak) id delegate;

最后在.m文件调用代理的方法

#pragma mark - 重写set方法,改变选中下标,调用代理方法

- (void)setSelectedIndex:(NSInteger)selectedIndex {

_selectedIndex = selectedIndex;

// 调用代理的方法

[self.delegate changeControllerWithIndex:self.selectedIndex];

}

(2)委托方

首先要准守协议方法

// 遵守协议方法

@interface WJTabBarController ()

然后去设置代理人,这个代理人应该是在tabBar被加载的时候就应该设置的,所以应该在wj_tabBar的懒加载中加上代理人的设置

#pragma mark - 懒加载

- (WJTabBar *)wj_tabBar {

if (!_wj_tabBar) {

_wj_tabBar = [[WJTabBar alloc]init];

_wj_tabBar.frame = self.tabBar.bounds;

_wj_tabBar.backgroundColor = [UIColor cyanColor];

// 设置代理人

_wj_tabBar.delegate = self;

}

return _wj_tabBar;

}

最后要实现代理方法,(这是委托人需要执行的)

#pragma mark - 实现协议方法(切换视图控制器)

- (void)changeControllerWithIndex:(NSInteger)index {

// 切换视图控制器

self.selectedIndex = index;

}

以上就是自定义按钮的大概实现步骤。

三:总结

要实现自定义的按钮,就是需要覆盖系统原生的按钮,然后移除tabBar上的所有子控件,然后在tabBar上去创建一个自定义的tabBar,然后在tabBar上创建按钮,在按钮上去创建图片和文字;如果要添加中间的那种特殊定制的按钮,只需要把frame值设置好就应该可以了。实现页面的切换的话,就需要用到代理,让tabBarController去实现tabBar想实现的功能就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值