转自:http://blog.csdn.net/xn4545945/article/details/35994863

一、自定义的思路

iOS中的TabBarController确实已经很强大了,大部分主流iOS应用都会采用。但是往往也不能满足全部的需求,因此需要自定义TabBar,自定义需要对系统的TabBar工作方式有很好的理解,自定义需要勇气。

自定义TabBar的原则:尽量利用系统自带TabBar,只改需要改的地方。

二、自定义TabBar的总体过程
1.先把自带的TabBar条给取消了
2.自己做一个view,上面放几个按钮,设定按钮的点击事件.并设置selectIndex。
3.关联各个子viewController,覆盖相关事件。

三、细节很重要

1. 让自己创建的按钮关联到viewController:
•用tabbar的selectedIndex属性.设置这个属性就行了.
2. 取消系统的高亮:
•可以自定义一个按钮.重写里面的setHighhighted方法,什么也不做就行了.(如果调用super就相当于没写)
3. 关于几个按钮只选中一个的方法:
•设置一个属性,记录上一个选中的按钮.
•点击当前按钮时,把上一个按钮设置为未选中,并把当前按钮设置为选中,最后把当前按钮赋值给上一个按钮.
四、初步自定义
直接上代码,详见注释。
 

XNTabBarController.h

  1. #import <UIKit/UIKit.h>

    @interface

    @end

XNTabBarController.m

  1. //
    //  XNTabBarController.m
    //
    //
    //  Created by neng on 14-6-19.
    //  Copyright (c) 2014年 neng. All rights reserved.
    //

    #import "XNTabBarController.h"
    #import "Common.h"
    #import "XNTabBarButton.h"

    @interface
    /**

  2. *  设置之前选中的按钮
  3. */
    @propertynonatomicUIButton
    @end

    @implementation

    void
    super];

  4. //    NSLog(@"%s",__func__);
    //    NSLog(@"%@",self.view.subviews); //能打印出所有子视图,和其frame

    self);

  5. self.frame
    self removeFromSuperview
  6. UIView]];
  7. = rect;
  8. = [UIColor];
  9. self addSubview

    forint; i < ; i++) {

  10. XNTabBarButton]];
  11. NSString:, i +];
  12. NSString:, i +];
  13. :[UIImage:imageName]:UIControlStateNormal];
  14. :[UIImage:imageNameSel]:UIControlStateSelected];
  15. i.size / ;
  16. = CGRectMake(x, , myView.size / , myView.size);
  17. :btn];
  18. = i;
  19. :self:@selector forControlEvents
  20. if == i) {
  21. = YES
    self = btn;
  22. /**
  23. *  自定义TabBar的按钮点击事件
  24. */
    voidUIButton
  25. self.selectedNO
  26. = YES
  27. self = button;
  28. self = button;
  29. @end

XNTabBarButton.h

  1. #import <UIKit/UIKit.h>

    @interface

    @end

XNTabBarButton.m

  1. #import "XNTabBarButton.h"

    @implementation
    /**什么也不做就可以取消系统按钮的高亮状态*/
    voidBOOL
    //    [super setHighlighted:highlighted];

    @end

五、代码重构

重构的目的是把代码放到他最该到的地方去. 提高可读写与可拓展性。
对控件的重构要保证可重用性. 做到封装做其他应用时,可以直接拿过去用的地步.
tips :
 
1、关于init与initWithFrame:
•在对象初始化调用init时,会调用initWithFrame方法.
•Init与initWithFrame都会被调用.
•建议自定义控件不要重写init方法,需要初始化时重写initWithFrame方法.
•好处:其他人调用无论是调用init,还是调用initWithFrame都会调用initWithFrame方法.
2、关于控件的布局代码:
•建议写在layoutSubviews方法中.
•不要忘记写super方法
•将设置x,y,frame等写在这里面.
3、将自定义的Tabbar添加为系统TabBar的子视图,这样TabBar的切换自动隐藏/滑动功能就不用自己做了.
(hidebottombaronpush)
重构后的代码如下
将自定义的TabBar单独建立,并将代码移过去。
设置代理方法,工具栏按钮被选中,记录从哪里跳转到哪里. 

XNTabBar.h

  1. #import <UIKit/UIKit.h>
    @class

    @protocol
    /**

  2. *  工具栏按钮被选中, 记录从哪里跳转到哪里. (方便以后做相应特效)
  3. */
    void tabBarXNTabBar:(NSInteger) from:(NSInteger)to;
  4. @end

    @interface
    @propertynonatomicid
    /**

  5. *  使用特定图片来创建按钮, 这样做的好处就是可扩展性. 拿到别的项目里面去也能换图片直接用
  6. *
  7. *  @param image         普通状态下的图片
  8. *  @param selectedImage 选中状态下的图片
  9. */
    voidUIImage:(UIImage
    @end

XNTabBar.m

  1. //
    //  XNTabBar.m
    //
    //  Created by neng on 14-6-19.
    //  Copyright (c) 2014年 neng. All rights reserved.
    //

    #import "XNTabBar.h"
    #import "XNTabBarButton.h"

    @interface
    /**

  2. *  设置之前选中的按钮
  3. */
    @propertynonatomicUIButton
    @end

    @implementation

    /**

  4. *  在这个方法里写控件初始化的东西, 调用init方法时会调用
  5. */
    //- (id)initWithFrame:(CGRect)frame {
    //  if (self = [super initWithFrame:frame]) {
    //      //添加按钮
    //      for (int i = 0; i < 5; i++) { //取消掉特定的数字
    //          //UIButton *btn = [[UIButton alloc] init];
    //          XNTabBarButton *btn = [[XNTabBarButton alloc] init];
    //
    //          NSString *imageName = [NSString stringWithFormat:@"TabBar%d", i + 1];
    //          NSString *imageNameSel = [NSString stringWithFormat:@"TabBar%dSel", i + 1];
    //
    //          [btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
    //          [btn setImage:[UIImage imageNamed:imageNameSel] forState:UIControlStateSelected];
    //
    //          [self addSubview:btn];
    //
    //          btn.tag = i; //设置按钮的标记, 方便来索引当前的按钮,并跳转到相应的视图
    //
    //          //带参数的监听方法记得加"冒号"
    //          [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
    //
    //          if (0 == i) {
    //              [self clickBtn:btn];
    //          }
    //      }
    //  }
    //  return self;
    //}

    voidUIImage:(UIImage
    UIButton]];

  6. :image:UIControlStateNormal];
  7. :selectedImage:UIControlStateSelected];
  8. self:btn];
  9. :self:@selector forControlEvents
  10. ifself.count) {
  11. self:btn];
  12. /**专门用来布局子视图, 别忘了调用super方法*/
    void
    super];
  13. intself.count
    forint; i < count; i++) {
  14. UIButtonself[i];
  15. = i;
  16. iself.size / count;
  17. ;
  18. self.size / count;
  19. self.size;
  20. = CGRectMake(x, y, width, height);
  21. /**
  22. *  自定义TabBar的按钮点击事件
  23. */
    voidUIButton
  24. self.selectedNO
  25. = YES
  26. self = button;
  27. ifself respondsToSelector@selector
    self tabBarself:self.tag:button];
  28. @end

原先的XNTabBarController.m经过修改后,注释了原先的代码。

  1. //
    //  XNTabBarController.m
    //
    //  Created by neng on 14-6-19.
    //  Copyright (c) 2014年 neng. All rights reserved.
    //

    #import "XNTabBarController.h"
    #import "XNTabBarButton.h"
    #import "XNTabBar.h"

    @interface
    /**

  2. *  设置之前选中的按钮
  3. */
    @propertynonatomicUIButton
    @end

    @implementation

    void
    super];

  4. //    NSLog(@"%s",__func__);
    //    NSLog(@"%@",self.view.subviews); //能打印出所有子视图,和其frame
    //  LogFun;
    //  LogSubviews(self.view);
  5. self.bounds
  6. self);
  7. XNTabBar]];
  8. = self
  9. = rect;
  10. self addSubview
  11. forint; i<self.count
  12. NSString:, i +];
  13. NSString:, i +];
  14. UIImage:imageName];
  15. UIImage:imageNameSel];
  16. :image:imageSel];
  17. //    //添加按钮
    //  for (int i = 0; i < 5; i++) {
    //      //UIButton *btn = [[UIButton alloc] init];
    //        XNTabBarButton *btn = [[XNTabBarButton alloc] init];
    //
    //      NSString *imageName = [NSString stringWithFormat:@"TabBar%d", i + 1];
    //      NSString *imageNameSel = [NSString stringWithFormat:@"TabBar%dSel", i + 1];
    //
    //      [btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
    //      [btn setImage:[UIImage imageNamed:imageNameSel] forState:UIControlStateSelected];
    //
    //      CGFloat x = i * myView.frame.size.width / 5;
    //      btn.frame = CGRectMake(x, 0, myView.frame.size.width / 5, myView.frame.size.height);
    //
    //      [myView addSubview:btn];
    //
    //        btn.tag = i;//设置按钮的标记, 方便来索引当前的按钮,并跳转到相应的视图
    //
    //      //带参数的监听方法记得加"冒号"
    //      [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
    //
    //      //设置刚进入时,第一个按钮为选中状态
    //      if (0 == i) {
    //          btn.selected = YES;
    //          self.selectedBtn = btn;  //设置该按钮为选中的按钮
    //      }
    //  }

    /**永远别忘记设置代理*/
    voidXNTabBar:(NSInteger)from:(NSInteger)to {

  18. self = to;
  19. /**
  20. *  自定义TabBar的按钮点击事件
  21. */
    //- (void)clickBtn:(UIButton *)button {
    //  //1.先将之前选中的按钮设置为未选中
    //  self.selectedBtn.selected = NO;
    //  //2.再将当前按钮设置为选中
    //  button.selected = YES;
    //  //3.最后把当前按钮赋值为之前选中的按钮
    //  self.selectedBtn = button;
    //
    //    //4.跳转到相应的视图控制器. (通过selectIndex参数来设置选中了那个控制器)
    //    self.selectedIndex = button.tag;
    //}

    @end

自定义后的效果图:

例子源码下载 http://download.csdn.net/detail/xn4545945/7572263

转载请注明出处:http://blog.csdn.net/xn4545945

iOS 自定义TabBarController的更多相关文章

  1. iOS 自定义tabBarController(中间弧形)

    效果图 1.在继承自UITabBarController的自定义controller中调用以下方法(LZCustomTabbar为自定义的tabbar) - (void)viewDidAppear:( ...

  2. 【iOS自定义键盘及键盘切换】详解

    [iOS自定义键盘]详解 实现效果展示: 一.实现的协议方法代码 #import <UIKit/UIKit.h> //创建自定义键盘协议 @protocol XFG_KeyBoardDel ...

  3. iOS自定义的UISwitch按钮

    UISwitch开关控件 开关代替了点选框.开关是到目前为止用起来最简单的控件,不过仍然可以作一定程度的定制化. 一.创建 UISwitch* mySwitch = [[ UISwitchalloc] ...

  4. 如何实现 iOS 自定义状态栏

    给大家介绍如何实现 iOS 自定义状态栏 Sample Code: 01 UIWindow * statusWindow = [[UIWindow alloc] initWithFrame:[UIAp ...

  5. iOS自定义组与组之间的距离以及视图

    iOS自定义组与组之间的距离以及视图 //头视图高度 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(N ...

  6. iOS 自定义转场动画

    代码地址如下:http://www.demodashi.com/demo/12955.html 一.总效果 本文记录分享下自定义转场动画的实现方法,具体到动画效果:新浪微博图集浏览转场效果.手势过渡动 ...

  7. iOS 自定义转场动画浅谈

    代码地址如下:http://www.demodashi.com/demo/11612.html 路漫漫其修远兮,吾将上下而求索 前记 想研究自定义转场动画很久了,时间就像海绵,挤一挤还是有的,花了差不 ...

  8. iOS自定义转场动画实战讲解

    iOS自定义转场动画实战讲解   转场动画这事,说简单也简单,可以通过presentViewController:animated:completion:和dismissViewControllerA ...

  9. iOS 实现Tabbarcontroller中间自定义样式 最简单的方法

    先上图: 如果我们要实现中间按钮自定义样式,方法应该蛮多,这里介绍一种最简单的. 1.创建类继承:UITabBarController,如下代码都是写在该类的 .m文件里 2.定义最中间的自定义样式, ...

随机推荐

  1. 最新JetBrains PyCharm 使用教程--安装教程(一)

    安装过程 ​ ​ ​ ​ ​ ​ ​ Pycharm  激活码 license server选项里边输入:http://intellij.mandroid.cn/ ​

  2. Spring Boot 2.X(十七):应用监控之 Spring Boot Admin 使用及配置

    Admin 简介 Spring Boot Admin 是 Spring Boot 应用程序运行状态监控和管理的后台界面.最新UI使用vue.js重写里. Spring Boot Admin 为已注册的 ...

  3. css3软键盘不盖住输入框的方法

    css3软键盘不盖住输入框的方法 弹出软键盘的时候 最外面的容器高度就发生了变化 要减去软键盘高度了<pre>var bodyheight bodyheight = $('body').h ...

  4. winds添加静态路由

    如上图所示,wan口设备箱访问路由器栏口设备 route -p add 192.168.21.0 mask 255.255.255.0  192.168.0.176 -p 表示永久路由,重启后不丢失 ...

  5. java架构之路(MQ专题)kafka集群配置和简单使用

    前面我们说了RabbitMQ和RocketMQ的安装和简单的使用,这次我们说一下Kafka的安装配置,后面我会用几个真实案例来说一下MQ的真实使用场景.天冷了,不愿意伸手,最近没怎么写博客了,还请见谅 ...

  6. spark集群搭建(三台虚拟机)——系统环境搭建(1)

    !!!该系列使用三台虚拟机搭建一个完整的spark集群,集群环境如下: virtualBox5.2.Ubuntu14.04.securecrt7.3.6_x64英文版(连接虚拟机) jdk1.7.0. ...

  7. 三、netcore跨平台之 Linux配置nginx负载均衡

    前面两章讲了netcore在linux上部署以及配置nginx,并让nginx代理webapi. 这一章主要讲如何配置负载均衡,有些步骤在前两章讲的很详细了,所以这一章我就不会一个个截图了. 因为本人 ...

  8. nyoj 53-不高兴的小明 (遍历)

    53-不高兴的小明 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:28 submit:89 题目描述:    小明又出问题了.妈妈认为聪明的小明应该 ...

  9. 学习记录:《C++设计模式——李建忠主讲》6.“状态变化”模式

    状态变化模式:在组件构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定.状态变化模式为这一问题提供了一种解决方案. 典型模式:状态模式(State).备忘录 ...

  10. python:利用celery分布任务

    Celery是一个功能完备即插即用的任务队列.它使得我们不需要考虑复杂的问题,使用非常简单.celery看起来似乎很庞大.celery适用异步处理问题,当发送邮件.或者文件上传, 图像处理等等一些比较 ...