iOS中定制tabBar,目前无非就两种方式:
第一种是继承系统的UITabBar,在子类里进行自定义修改,实例化之后利用KVC setTabBar: 即可
第二种是自定义View,创建若干个需要的按钮,按钮的点击事件去Hook系统的TabBar Item的点击事件,主要是系统的TabBarController的一个属性,即selectedIndex 起到切换子控制器的作用,也就是说按钮的选中事件和切换子控制器是一致的,利用下标去映射就ok啦
首先拿到问题,进行如下分析:
- 1 自定义需要什么东西 ?
- 2 需要实现什么样的功能?
- 3 代码如何封装,可复用性和稳定性更高?
- 4 用什么方式实现的更优雅,更简单可控
......
#1. 自定义需要准备好图片(选中与常态下的两套图标)
#2. 有特殊需求的时候才需要特别定制,一般情况下监听点击事情,模仿系
#统切换子控制器的动作即可
#3. 一般会做成公共的API调用接口,如果是在系统的基础上修改,
#使用代理无疑是更优雅的选择,直接使用系统的代理, 如果是自定义的
#话,block和代理均可,个人比较倾向于使用代理
#4. 如果是继承系统的UITabBar的基础上进行修改的话,建议用纯代码,
#因为这样修改起来比较方便, 对于自定义View的方式来定制的话,如果是
#简单的监听点击或者不是什么复杂UI,我倒是觉得XIB也无伤大雅,怎么
#简单怎么来,除非是情况比较复杂,那就只得纯代码来怼.
废话不多说,进入正题,这里对于系统的UITabBar简单定制不再作过多獒述,网上太多类似教程, 基本上是开箱即用
XIB定制 ----自定义View实现TabBar功能
拽UI
根据自己业务和UI进行拖拽
拉约束
只可意会,不可描述,拉得多了自然就会了
添加监听事件
直接拖线就好辣,还讲个鬼哦
处理点击逻辑
判断选中与未选中两种状态下的显示逻辑
打通UITabBarController
selectedIndex
与 按钮选中下标是一致的就ok👌
文笔不好,老老实实做笔记,贴代码大法
<!--- TabBar --->
@protocol WGBTabBarDelegate <NSObject>
- (void)selectedClickWithIndex:(NSInteger)index;
@end
@interface WGBTabBar : UIView
@property (nonatomic,weak) id<WGBTabBarDelegate> wgbDelegate;
@end
#import "WGBTabBar.h"
@interface WGBTabBar ()
@property (nonatomic,strong) UIButton *tempButton;
@property (weak, nonatomic) IBOutlet UIButton *oneButton;
@end
@implementation WGBTabBar
- (void)awakeFromNib{
[super awakeFromNib];
self.tempButton = self.oneButton;
}
/// 0,1,2,3
- (IBAction)tabbarClickAction:(UIButton *)sender {
sender.backgroundColor = [UIColor blueColor];
self.tempButton.backgroundColor = [UIColor purpleColor];
self.tempButton.selected = NO;
self.tempButton = sender;
if ([self.wgbDelegate respondsToSelector: @selector(selectedClickWithIndex:)]) {
[self.wgbDelegate selectedClickWithIndex: sender.tag];
}
}
@end
<!--- TabBarViewController --->
#import "WGBTabBarViewController.h"
#import "WGBTabBar.h"
#import "OneViewController.h"
#import "TwoViewController.h"
#import "ThreeViewController.h"
#import "FourViewController.h"
@interface WGBTabBarViewController ()<WGBTabBarDelegate>
@end
@implementation WGBTabBarViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self createTabBar];
[self initViewContreollers];
}
- (void)createTabBar{
CGFloat kWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat kHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat kTabBarHeight = 49;
WGBTabBar *tabBar = [[NSBundle mainBundle] loadNibNamed:@"WGBTabBar" owner:nil options:0][0];
tabBar.wgbDelegate = self;
tabBar.frame = CGRectMake(0, kHeight - kTabBarHeight, kWidth , kTabBarHeight);
self.tabBar.hidden = YES; ///这句代码很关键 ,之前没隐藏,总感觉有什么东西挡住
[self.view addSubview: tabBar] ;
}
#pragma mark- <WGBTabBarDelegate>
- (void)selectedClickWithIndex:(NSInteger)index{
self.selectedIndex = index;
}
- (void)initViewContreollers{
OneViewController *oneVC = [[OneViewController alloc] init];
TwoViewController *twoVC = [[TwoViewController alloc] init];
ThreeViewController *threeVC = [[ThreeViewController alloc] init];
FourViewController *fourVC = [[FourViewController alloc] init];
NSArray *VCs = @[oneVC,twoVC,threeVC,fourVC];
NSMutableArray *childsVC = [NSMutableArray array];
for (UIViewController *VC in VCs) {
UINavigationController *rootVC = [[UINavigationController alloc] initWithRootViewController:VC];
VC.title = NSStringFromClass([VC class]);
[childsVC addObject: rootVC];
}
self.viewControllers = childsVC;
}
@end
(Tips)注意:
系统的tabBar一定要隐藏掉,不然会干扰点击事件,让你产生错觉,内部实现不隐藏的话应该是会放到最上层
做了一个最简单的,没有添加图片,纯文字表达一下意思咯,意思意思咯
2017 年 07 月 12日 更新一个新姿势
如何优雅的隐藏tabBar?
除了将自定义tabBar的hidden
属性提出来,似乎并没有什么太好的方案. 而hook系统的"hidesBottomBarWhenPushed"属性,这个需要继承系统的UITabBar定制的才适用.
下面简述一下我的做法
#1. 将自定义view(即tabBar) 的hidden属性提取出来,可以通过Appdelegate 做成全局的属性
#2. 在基类里定义一个属性,hideTabBar,用于获取子类设置的显示或者隐藏的状态进行操作
#3. 在最外层,也就是TabBarController包裹的子VC里的
#`- (void)viewWillAppear:(BOOL)animated`
# `- (void)viewWillDisappear:(BOOL)animated`
#这两个方法里设置显示或者隐藏
#4. 在点击TabBar那个监听方法里,设置自定义TabBar一直显示,不然会出现切换TabBarController子控制器的也会出现忽闪忽闪的感觉...
贴代码大法:
step 1
#import <UIKit/UIKit.h>
#import "WGBTabBar.h"
@interface WGBTabBarViewController : UITabBarController
@property (nonatomic,strong) WGBTabBar *wgbTabBar;
@end
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (nonatomic,strong) WGBTabBarViewController *tabBarController ;
@end
step 2
- (void)setHiddenTabBar:(BOOL)hiddenTabBar{
_hiddenTabBar = hiddenTabBar;
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.tabBarController.wgbTabBar.hidden = hiddenTabBar;
}
step 3
在首页那个层级的VC里如下方法设置:
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.hiddenTabBar = NO;
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
self.hiddenTabBar = YES;
}
step 4
#pragma mark- <WGBTabBarDelegate>
- (void)selectedClickWithIndex:(NSInteger)index{
self.selectedIndex = index;
self.wgbTabBar.hidden = NO;
}