iOS 自定义TabBarController zhuanzai

iOS 自定义TabBarController

一、自定义的思路

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

[objc] view plaincopy

  1. #import <UIKit/UIKit.h>
  2. @interface XNTabBarController : UITabBarController
  3. @end

XNTabBarController.m

[objc] view plaincopy

  1. //
  2. //  XNTabBarController.m
  3. //
  4. //
  5. //  Created by neng on 14-6-19.
  6. //  Copyright (c) 2014年 neng. All rights reserved.
  7. //
  8. #import "XNTabBarController.h"
  9. #import "Common.h"
  10. #import "XNTabBarButton.h"
  11. @interface XNTabBarController ()
  12. /**
  13. *  设置之前选中的按钮
  14. */
  15. @property (nonatomic, weak) UIButton *selectedBtn;
  16. @end
  17. @implementation XNTabBarController
  18. - (void)viewDidLoad {
  19. [super viewDidLoad];
  20. //下面两个方法在开发中是经常会用到的
  21. //    NSLog(@"%s",__func__);
  22. //    NSLog(@"%@",self.view.subviews); //能打印出所有子视图,和其frame
  23. LogFun;
  24. LogSubviews(self.view);
  25. //删除现有的tabBar
  26. CGRect rect = self.tabBar.frame;
  27. [self.tabBar removeFromSuperview];  //移除TabBarController自带的下部的条
  28. //测试添加自己的视图
  29. UIView *myView = [[UIView alloc] init];
  30. myView.frame = rect;
  31. myView.backgroundColor = [UIColor redColor];
  32. [self.view addSubview:myView];
  33. for (int i = 0; i < 5; i++) {
  34. //UIButton *btn = [[UIButton alloc] init];
  35. XNTabBarButton *btn = [[XNTabBarButton alloc] init];
  36. NSString *imageName = [NSString stringWithFormat:@"TabBar%d", i + 1];
  37. NSString *imageNameSel = [NSString stringWithFormat:@"TabBar%dSel", i + 1];
  38. [btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
  39. [btn setImage:[UIImage imageNamed:imageNameSel] forState:UIControlStateSelected];
  40. CGFloat x = i * myView.frame.size.width / 5;
  41. btn.frame = CGRectMake(x, 0, myView.frame.size.width / 5, myView.frame.size.height);
  42. [myView addSubview:btn];
  43. btn.tag = i;//设置按钮的标记, 方便来索引当前的按钮,并跳转到相应的视图
  44. //带参数的监听方法记得加"冒号"
  45. [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
  46. //设置刚进入时,第一个按钮为选中状态
  47. if (0 == i) {
  48. btn.selected = YES;
  49. self.selectedBtn = btn;  //设置该按钮为选中的按钮
  50. }
  51. }
  52. }
  53. /**
  54. *  自定义TabBar的按钮点击事件
  55. */
  56. - (void)clickBtn:(UIButton *)button {
  57. //1.先将之前选中的按钮设置为未选中
  58. self.selectedBtn.selected = NO;
  59. //2.再将当前按钮设置为选中
  60. button.selected = YES;
  61. //3.最后把当前按钮赋值为之前选中的按钮
  62. self.selectedBtn = button;
  63. //4.跳转到相应的视图控制器. (通过selectIndex参数来设置选中了那个控制器)
  64. self.selectedIndex = button.tag;
  65. }
  66. @end

XNTabBarButton.h

[objc] view plaincopy

  1. #import <UIKit/UIKit.h>
  2. @interface XNTabBarButton : UIButton
  3. @end

XNTabBarButton.m

[objc] view plaincopy

  1. #import "XNTabBarButton.h"
  2. @implementation XNTabBarButton
  3. /**什么也不做就可以取消系统按钮的高亮状态*/
  4. - (void)setHighlighted:(BOOL)highlighted{
  5. //    [super setHighlighted:highlighted];
  6. }
  7. @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

[objc] view plaincopy

  1. #import <UIKit/UIKit.h>
  2. @class XNTabBar;
  3. @protocol XNTabBarDelegate <NSObject>
  4. /**
  5. *  工具栏按钮被选中, 记录从哪里跳转到哪里. (方便以后做相应特效)
  6. */
  7. - (void) tabBar:(XNTabBar *)tabBar selectedFrom:(NSInteger) from to:(NSInteger)to;
  8. @end
  9. @interface XNTabBar : UIView
  10. @property(nonatomic,weak) id<XNTabBarDelegate> delegate;
  11. /**
  12. *  使用特定图片来创建按钮, 这样做的好处就是可扩展性. 拿到别的项目里面去也能换图片直接用
  13. *
  14. *  @param image         普通状态下的图片
  15. *  @param selectedImage 选中状态下的图片
  16. */
  17. -(void)addButtonWithImage:(UIImage *)image selectedImage:(UIImage *) selectedImage;
  18. @end

XNTabBar.m

[objc] view plaincopy

  1. //
  2. //  XNTabBar.m
  3. //
  4. //  Created by neng on 14-6-19.
  5. //  Copyright (c) 2014年 neng. All rights reserved.
  6. //
  7. #import "XNTabBar.h"
  8. #import "XNTabBarButton.h"
  9. @interface XNTabBar ()
  10. /**
  11. *  设置之前选中的按钮
  12. */
  13. @property (nonatomic, weak) UIButton *selectedBtn;
  14. @end
  15. @implementation XNTabBar
  16. /**
  17. *  在这个方法里写控件初始化的东西, 调用init方法时会调用
  18. */
  19. //- (id)initWithFrame:(CGRect)frame {
  20. //  if (self = [super initWithFrame:frame]) {
  21. //      //添加按钮
  22. //      for (int i = 0; i < 5; i++) { //取消掉特定的数字
  23. //          //UIButton *btn = [[UIButton alloc] init];
  24. //          XNTabBarButton *btn = [[XNTabBarButton alloc] init];
  25. //
  26. //          NSString *imageName = [NSString stringWithFormat:@"TabBar%d", i + 1];
  27. //          NSString *imageNameSel = [NSString stringWithFormat:@"TabBar%dSel", i + 1];
  28. //
  29. //          [btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
  30. //          [btn setImage:[UIImage imageNamed:imageNameSel] forState:UIControlStateSelected];
  31. //
  32. //          [self addSubview:btn];
  33. //
  34. //          btn.tag = i; //设置按钮的标记, 方便来索引当前的按钮,并跳转到相应的视图
  35. //
  36. //          //带参数的监听方法记得加"冒号"
  37. //          [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
  38. //
  39. //          if (0 == i) {
  40. //              [self clickBtn:btn];
  41. //          }
  42. //      }
  43. //  }
  44. //  return self;
  45. //}
  46. - (void)addButtonWithImage:(UIImage *)image selectedImage:(UIImage *)selectedImage {
  47. UIButton *btn = [[UIButton alloc] init];
  48. [btn setImage:image forState:UIControlStateNormal];
  49. [btn setImage:selectedImage forState:UIControlStateSelected];
  50. [self addSubview:btn];
  51. //带参数的监听方法记得加"冒号"
  52. [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
  53. //如果是第一个按钮, 则选中(按顺序一个个添加)
  54. if (self.subviews.count == 1) {
  55. [self clickBtn:btn];
  56. }
  57. }
  58. /**专门用来布局子视图, 别忘了调用super方法*/
  59. - (void)layoutSubviews {
  60. [super layoutSubviews];
  61. int count = self.subviews.count;
  62. for (int i = 0; i < count; i++) {
  63. //取得按钮
  64. UIButton *btn = self.subviews[i];
  65. btn.tag = i; //设置按钮的标记, 方便来索引当前的按钮,并跳转到相应的视图
  66. CGFloat x = i * self.bounds.size.width / count;
  67. CGFloat y = 0;
  68. CGFloat width = self.bounds.size.width / count;
  69. CGFloat height = self.bounds.size.height;
  70. btn.frame = CGRectMake(x, y, width, height);
  71. }
  72. }
  73. /**
  74. *  自定义TabBar的按钮点击事件
  75. */
  76. - (void)clickBtn:(UIButton *)button {
  77. //1.先将之前选中的按钮设置为未选中
  78. self.selectedBtn.selected = NO;
  79. //2.再将当前按钮设置为选中
  80. button.selected = YES;
  81. //3.最后把当前按钮赋值为之前选中的按钮
  82. self.selectedBtn = button;
  83. //却换视图控制器的事情,应该交给controller来做
  84. //最好这样写, 先判断该代理方法是否实现
  85. if ([self.delegate respondsToSelector:@selector(tabBar:selectedFrom:to:)]) {
  86. [self.delegate tabBar:self selectedFrom:self.selectedBtn.tag to:button.tag];
  87. }
  88. //4.跳转到相应的视图控制器. (通过selectIndex参数来设置选中了那个控制器)
  89. //self.selectedIndex = button.tag;
  90. }
  91. @end

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

[objc] view plaincopy

  1. //
  2. //  XNTabBarController.m
  3. //
  4. //  Created by neng on 14-6-19.
  5. //  Copyright (c) 2014年 neng. All rights reserved.
  6. //
  7. #import "XNTabBarController.h"
  8. #import "XNTabBarButton.h"
  9. #import "XNTabBar.h"
  10. @interface XNTabBarController () <XNTabBarDelegate>
  11. /**
  12. *  设置之前选中的按钮
  13. */
  14. @property (nonatomic, weak) UIButton *selectedBtn;
  15. @end
  16. @implementation XNTabBarController
  17. - (void)viewDidLoad {
  18. [super viewDidLoad];
  19. //下面两个方法在开发中是经常会用到的
  20. //    NSLog(@"%s",__func__);
  21. //    NSLog(@"%@",self.view.subviews); //能打印出所有子视图,和其frame
  22. //  LogFun;
  23. //  LogSubviews(self.view);
  24. //Hell
  25. //删除现有的tabBar
  26. CGRect rect = self.tabBar.bounds; //这里要用bounds来加, 否则会加到下面去.看不见
  27. LogFrame(self.tabBar);
  28. //[self.tabBar removeFromSuperview];  //移除TabBarController自带的下部的条
  29. //测试添加自己的视图
  30. XNTabBar *myView = [[XNTabBar alloc] init]; //设置代理必须改掉前面的类型,不能用UIView
  31. myView.delegate = self; //设置代理
  32. myView.frame = rect;
  33. [self.tabBar addSubview:myView]; //添加到系统自带的tabBar上, 这样可以用的的事件方法. 而不必自己去写
  34. //为控制器添加按钮
  35. for (int i=0; i<self.viewControllers.count; i++) { //根据有多少个子视图控制器来进行添加按钮
  36. NSString *imageName = [NSString stringWithFormat:@"TabBar%d", i + 1];
  37. NSString *imageNameSel = [NSString stringWithFormat:@"TabBar%dSel", i + 1];
  38. UIImage *image = [UIImage imageNamed:imageName];
  39. UIImage *imageSel = [UIImage imageNamed:imageNameSel];
  40. [myView addButtonWithImage:image selectedImage:imageSel];
  41. }
  42. //    //添加按钮
  43. //  for (int i = 0; i < 5; i++) {
  44. //      //UIButton *btn = [[UIButton alloc] init];
  45. //        XNTabBarButton *btn = [[XNTabBarButton alloc] init];
  46. //
  47. //      NSString *imageName = [NSString stringWithFormat:@"TabBar%d", i + 1];
  48. //      NSString *imageNameSel = [NSString stringWithFormat:@"TabBar%dSel", i + 1];
  49. //
  50. //      [btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
  51. //      [btn setImage:[UIImage imageNamed:imageNameSel] forState:UIControlStateSelected];
  52. //
  53. //      CGFloat x = i * myView.frame.size.width / 5;
  54. //      btn.frame = CGRectMake(x, 0, myView.frame.size.width / 5, myView.frame.size.height);
  55. //
  56. //      [myView addSubview:btn];
  57. //
  58. //        btn.tag = i;//设置按钮的标记, 方便来索引当前的按钮,并跳转到相应的视图
  59. //
  60. //      //带参数的监听方法记得加"冒号"
  61. //      [btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
  62. //
  63. //      //设置刚进入时,第一个按钮为选中状态
  64. //      if (0 == i) {
  65. //          btn.selected = YES;
  66. //          self.selectedBtn = btn;  //设置该按钮为选中的按钮
  67. //      }
  68. //  }
  69. }
  70. /**永远别忘记设置代理*/
  71. - (void)tabBar:(XNTabBar *)tabBar selectedFrom:(NSInteger)from to:(NSInteger)to {
  72. self.selectedIndex = to;
  73. }
  74. /**
  75. *  自定义TabBar的按钮点击事件
  76. */
  77. //- (void)clickBtn:(UIButton *)button {
  78. //  //1.先将之前选中的按钮设置为未选中
  79. //  self.selectedBtn.selected = NO;
  80. //  //2.再将当前按钮设置为选中
  81. //  button.selected = YES;
  82. //  //3.最后把当前按钮赋值为之前选中的按钮
  83. //  self.selectedBtn = button;
  84. //
  85. //    //4.跳转到相应的视图控制器. (通过selectIndex参数来设置选中了那个控制器)
  86. //    self.selectedIndex = button.tag;
  87. //}
  88. @end

自定义后的效果图:

me;

1.tabbarcontroller 的子控制器中包含(v1,v2,v3,v4,v5)v1的导航控制器所带的item点击事件无法响应。(去看天云聚合)

时间: 2024-12-24 00:58:03

iOS 自定义TabBarController zhuanzai的相关文章

iOS 自定义TabBarController

转自:http://blog.csdn.net/xn4545945/article/details/35994863 一.自定义的思路 iOS中的TabBarController确实已经很强大了,大部分主流iOS应用都会采用.但是往往也不能满足全部的需求,因此需要自定义TabBar,自定义需要对系统的TabBar工作方式有很好的理解,自定义需要勇气. 自定义TabBar的原则:尽量利用系统自带TabBar,只改需要改的地方. 二.自定义TabBar的总体过程 1.先把自带的TabBar条给取消了

【iOS】自定义TabBarController

一.自定义的思路 iOS中的TabBarController确实已经很强大了,大部分主流iOS应用都会采用.但是往往也不能满足全部的需求,因此需要自定义TabBar,自定义需要对系统的TabBar工作方式有很好的理解,自定义需要勇气. 自定义TabBar的原则:尽量利用系统自带TabBar,只改需要改的地方. 二.自定义TabBar的总体过程 1.先把自带的TabBar条给取消了 2.自己做一个view,上面放几个按钮,设定按钮的点击事件.并设置selectIndex. 3.关联各个子viewC

IOS 自定义 滑动返回 手势

/** 只需要在你自定义的导航控制器中,改成如下代码即可,自定义手势返回 */ #define KEY_WINDOW [[UIApplication sharedApplication] keyWindow] #define kScreenW KEY_WINDOW.bounds.size.width #define kAnimateDuration 0.3 #define kDefaultAlapa 0.5 #define kDefaultScale 0.95 #define iOS7 ([UI

IOS 自定义UIBUTTON 直接拖个xib 就能在button上显示多行文本 并且添加了点击的效果

拖个button继承一下  几行代码 就搞定 自用效果还行 IOS 自定义UIBUTTON 直接拖个xib 就能在button上显示多行文本 并且添加了点击的效果,布布扣,bubuko.com

iOS 自定义页面的切换动画与交互动画

在iOS7之前,开发者为了寻求自定义Navigation Controller的Push/Pop动画,只能受限于子类化一个UINavigationController,或是用自定义的动画去覆盖它.但是随着iOS7的到来,Apple针对开发者推出了新的工具,以更灵活地方式管理UIViewController切换. 自定义导航栏的Push/Pop动画 为了在基于UINavigationController下做自定义的动画切换,先建立一个简单的工程,这个工程的rootViewController是一个

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

iOS自定义转场动画实战讲解 转场动画这事,说简单也简单,可以通过presentViewController:animated:completion:和dismissViewControllerAnimated:completion:这一组函数以模态视图的方式展现.隐藏视图.如果用到了navigationController,还可以调用pushViewController:animated:和popViewController这一组函数将新的视图控制器压栈.弹栈. 下图中所有转场动画都是自定义的

自定义TabBarController报错 - Unbalanced calls to begin/end appearance transitions for &lt;&gt;

自定义了TabBarController 之后必须实现以下方法才能避免报错 -(void)viewWillAppear:(BOOL)animated { [self.selectedViewController beginAppearanceTransition: YES animated: animated]; } -(void) viewDidAppear:(BOOL)animated { [self.selectedViewController endAppearanceTransitio

iOS自定义tabbar后popToRootViewContriller和poptoviewcontroller时出现两个tabbar 的解决办法

iOS自定义tabbar后popToRootViewContriller和poptoviewcontroller时出现两个tabbar  的解决办法 问题:iOS自定义tabbar后popToRootViewContriller和poptoviewcontroller时出现两个tabbar 1.自定义代码: - (void)viewWillAppear:(BOOL)animated { [super  viewWillAppear:animated]; // 删除系统自动生成的UITabBarB

IOS开发—IOS自定义任意位置右滑POP视图控制器

IOS自定义任意位置右滑POP视图控制器 IOS7.0之后系统提供了原生的从左边缘滑动pop出栈的方法,也可以自定义左边缘pop出栈,将在下一篇介绍,本篇介绍通过添加手势的方法实现IOS当前屏幕任意位置(非指定左边缘)右滑pop视图控制器出栈.代码如下: // // LXXPopViewController.m // 任意点右滑Pop // // Created by Lotheve on 15/6/12. // Copyright (c) 2015年Lotheve. All rights re