1、UITabBarController的使用步骤
初始化UITabBarController
设置UIWindow的rootViewController为UITabBarController
根据具体情况,通过addChildViewController方法添加对应个数的子控制器
2、UITabBarController的子控制器
UITabBarController添加控制器的方式有2种
添加单个子控制器
- (void)addChildViewController:(UIViewController *)childController;
设置子控制器数组
@property(nonatomic,copy) NSArray *viewControllers;
3、UITabBar
如果UITabBarController有N个子控制器,那么UITabBar内部就会有N个UITabBarButton作为子控件
如果UITabBarController有4个子控制器,那么UITabBar的结构大致如下图所示
4、UITabBarButton
二、UITabBarController
如果系统的 UITabBarButton 不能满足我们的开发 , 比如 下列这种效果:
有两种三种方法去实现它:
第一种: 在我们 给TabBarController 添加子控制器的时间 ,在 第三的位置 加入一个 UIViewController ,需要放button的位置 撑开 ,然后定义一个 属性button,
@property (nonatomic , weak) UIButton *centerButton ;
- (void)customBtn{
if ( _centerButton == nil) {
_centerButton = [[UIButton alloc]init];
}
//长度
CGFloat w = self.tabBar.bounds.size.width / self.childViewControllers.count;
CGRect rect = CGRectMake(0, 0, w, self.tabBar.bounds.size.height);
//设置frmae
_centerButton.frame = CGRectOffset(rect, 2 * w, 0);
[_centerButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
[_centerButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
//设置背景图片
[_centerButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
[_centerButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
//设置一个监听事件
[_centerButton addTarget:self action:@selector(clickAdd) forControlEvents:UIControlEventTouchUpInside];
[self.tabBar addSubview:_centerButton];
}
注意 custom的调用位置 :
1、- (void)viewDidLayoutSubviews
2、- (void)viewWillAppear:(BOOL)animated
第二种方式
第二种方法:
1、自定义 整个 TabBar ,利用 layoutSubviews 这个 方法去设置每一个button的 frame ,把原来 view的 self.tabBar 移除 ,替换成我们定义的tabBar
2、在创建控制器的时间 把自定义那个 button添加到TabBar上,在根据按钮的不同的tag值去实现 代理,点击切换不同控制器
- (void)addTabBarButton:(UITabBarItem *)item
{
//创建按
TSZTabBarButton *button = [TSZTabBarButton buttonWithType:UIButtonTypeCustom];
//添加
[self addSubview:button];
//设置图片
[button setBackgroundImage:item.image forState:UIControlStateNormal];
[button setBackgroundImage:item.selectedImage forState:UIControlStateSelected];
//点击添加单击时间
[button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchDown];
//默认选中第0个按钮
NSInteger count = self.subviews.count;
if( 1 == count)
{
[self clickButton:button];
}
}
//给我们创建出来的加frame
- (void)layoutSubviews
{
NSInteger count = self.subviews.count;
CGFloat btnW = self.frame.size.width/5;
CGFloat btnH = self.frame.size.height;
//循环创建
for(int i =0 ; i< count;i++)
{
//取出创建的按钮
UIButton *btn = self.subviews[i];
CGFloat btnY = 0;
CGFloat btnX = btnW * i;
//设置frame
btn.frame = CGRectMake(btnX, btnY,btnW , btnH);
//设置按钮的tag
btn.tag = i;
}
}
#pragma mark --- 点击事件的实现
//点击事件的实现
- (void)clickButton:(UIButton *)btn
{
//通知代理,使用懒加载的方式
if([self.delegate respondsToSelector:@selector(tabBar:didselectedButtonFrom:to:)])
{
[self.delegate tabBar:self didselectedButtonFrom:self.currentSelectedBtn.tag to:btn.tag];
}
//取消上一次选中
self.currentSelectedBtn.selected = NO;
//设置按钮为选中
btn.selected = YES;
//记当前选中
self.currentSelectedBtn = btn;
}
第三种
第三种方法:自定义 TabBar , 但是只是 创建一个需要的button , 在layoutSubviews 布局子控件必须这样写 , 的时候进行判断
//判断 UITabBarButton是TabBar上 的 按钮
Class class = NSClassFromString(@"UITabBarButton");
if ([child isKindOfClass:class]) {
//设置宽度
child.width = tabW;
//设置x 的坐标
child.x = tabIndex * tabW ;
//增加索引
tabIndex++;
//中间的发送按钮不是UITabBarButton 是我们自定义的
if (tabIndex == 2){
tabIndex++;
}
}
如果是 它的子控件就是 tanBarItem 按照 计算设置frame ,先固定放置的按钮。
把创建好的button放上去就好了 , 只需要给这个一个按钮设置一个代理就可以完成界面的切换
//布局子控件
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//设置所需要的button
[self setupBtn];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
//设置所需要的button
[self setupBtn];
}
return self;
}
#pragma mark: 实现所需要的button
- (void)setupBtn{
//添加一个按钮到tabBar上
UIButton *btn = [[UIButton alloc]init];
//设置背景颜色
[btn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
[btn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
[btn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
//设置frame ,按钮的大小和背景图片的大小一致
btn.size = btn.currentBackgroundImage.size;
[self addSubview:btn];
//使用它
self.plusBtn = btn ;
}
#pragma mark:layoutSubviews 布局子控件必须这样写
- (void)layoutSubviews{
[super layoutSubviews];
//循环添加按钮
//1、设置发送按钮的位置
self.plusBtn.centerX = self.width * 0.5;
self.plusBtn.centerY = self.height * 0.5;
//设置其他位置的尺寸
CGFloat tabW = self.width / 5 ;
//当前tab的索引
CGFloat tabIndex = 0;
for (UIView *child in self.subviews) {
//判断 UITabBarButton是TabBar上 的 按钮
Class class = NSClassFromString(@"UITabBarButton");
if ([child isKindOfClass:class]) {
//设置宽度
child.width = tabW;
//设置x 的坐标
child.x = tabIndex * tabW ;
//增加索引
tabIndex++;
//中间的发送按钮不是UITabBarButton 是我们自定义的
if (tabIndex == 2){
tabIndex++;
}
}
}
}
三 、实现 这一种效果
1、swift的实现
1、 必须是自定义整个tabBar ,使用 核心动画 做个一个背景 ,在把白色的背景添加到 tabBar上,在layoutSubviews 上去设置所有 子控件的 frame ,在点击的时间实现 背景的动画效果
下面是swift的这个效果
/// 定义一个代理
protocol TSZTabBarDelegate: NSObjectProtocol {
func tabBar(tabBar:TSZTabBar , toIndex: Int)
}
class TSZTabBar: UIView {
//定义全局属性
var currentBtnSelect: UIButton?
var backImage:UIImageView?
weak var delegate: TSZTabBarDelegate?
/**
通过代码添加按钮
*/
override init(frame: CGRect) {
super.init(frame: frame)
self.addBackGround()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//MARK - 添加按钮
func addButtonWithBarItem(tabItem:UITabBarItem){
//创建按钮
let btn = UIButton()
//添加到view
self.addSubview(btn)
//设置图片
btn.setImage(tabItem.image, forState: UIControlState.Normal)
btn.setImage(tabItem.selectedImage, forState: UIControlState.Selected)
//添加监听事件
btn.addTarget(self, action: "btnCilck:", forControlEvents: UIControlEvents.TouchDown)
//默认设置选中第0个按钮
let count:Int = self.subviews.count
if 1 == count{
btnCilck(btn)
}
}
func btnCilck(btn: UIButton){
//设置按钮的选中状态
currentBtnSelect?.selected = false
btn.selected = true
//赋值
currentBtnSelect = btn
//改变背景颜色
UIView.animateWithDuration(0.5) { () -> Void in
// backImage.x = btn.x
backImage?.frame.origin.x = btn.frame.origin.x
}
//启动代理
delegate?.tabBar(self, toIndex: btn.tag)
}
/**
*布局子控件
*/
override func layoutSubviews() {
super.layoutSubviews()
let count = self.subviews.count - 1
let tabBarW = self.bounds.size.width
let tabBarH = self.bounds.size.height
//设置背景色图片的frame
backImage?.frame = CGRectMake(0, 5, tabBarW / CGFloat(count), tabBarH)
//btn的大小
let btnY:CGFloat = 0
let btnW = tabBarW / CGFloat(count)
let btnH = tabBarH
for i in 1...count{
//取出对应的button
let btn: UIView = self.subviews[i]
//计算frame
let btnX: CGFloat = CGFloat(i - 1)*btnW
//设置frame
btn.frame = CGRectMake(btnX, btnY, btnW, btnH)
btn.tag = i-1
}
}
//添加背景图片
func addBackGround(){
let backGround: UIImageView = UIImageView()
backGround.image = UIImage(named: "toolBar_shade")
backImage = backGround
self.addSubview(backImage!)
}
//画图
override func drawRect(rect: CGRect) {
let image: UIImage = UIImage(named: "tabBar_back")!
image .drawInRect(rect)
}
}
2、OC的实现
#pragma - mark 通过代码添加background
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self addBackground];
}
return self;
}
#pragma - mark 添加按钮
- (void)addButtonWithtabBarItem:(UITabBarItem *)tabItem
{
// 创建按钮
HMTabBarButton * btn = [[HMTabBarButton alloc] init];
[self addSubview:btn];
// 设置图片
[btn setImage:tabItem.image forState:UIControlStateNormal];
[btn setImage:tabItem.selectedImage forState:UIControlStateSelected];
// 监听点击事件
[btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];
// 设置默认选中第0个按钮
NSInteger count = self.subviews.count;
if(2 == count)
{
[self btnClick:btn];
}
}
#pragma - mark 添加按钮背景图片
- (void)addBackground
{
// 添加白色图片
UIImageView *backGroundImage = [[UIImageView alloc] init];
backGroundImage.image = [UIImage imageNamed:@"toolBar_shade"];
self.backGroundImage = backGroundImage;
[self addSubview:backGroundImage];
}
#pragma - mark 选中按钮
- (void)btnClick:(HMTabBarButton *)btn
{
// 设置按钮的选中状态
self.currentSelBtn.selected = NO;
btn.selected = YES;
self.currentSelBtn = btn;
// 改变backGroundImage的frame
[UIView animateWithDuration:0.3 animations:^{
self.backGroundImage.x = btn.x;
}];
// 通知控制器切换子控制器
if ([self.delegate respondsToSelector:@selector(tabBar:toIndex:)]) {
[self.delegate tabBar:self toIndex:(int)btn.tag];
}
}
#pragma - mark 布局子控件
- (void)layoutSubviews
{
NSInteger count = self.subviews.count - 1;
CGFloat tabBarW = self.bounds.size.width;
CGFloat tabBarH = self.bounds.size.height;
// 设置backGroundImage的frame
self.backGroundImage.frame = CGRectMake(0, 5, tabBarW / count, tabBarH);
CGFloat btnY = 0;
CGFloat btnW = tabBarW / count;
CGFloat btnH = tabBarH;
for (int i = 1; i <= count; i++) {
// 取出对应的按钮
HMTabBarButton * btn = self.subviews[i];
// 计算frame
CGFloat btnX = (i - 1)* btnW;
// 设置frame
btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
// 设置按钮tag
btn.tag = i - 1;
}
}
#pragma - mark 画出大背景图片
- (void)drawRect:(CGRect)rect
{
UIImage * image = [UIImage imageNamed:@"tabBar_back"];
[image drawInRect:rect];
}