iOS开发之自定义TabBarController-present(模态)出控制器
2016-09-22 23:05
966 查看
如上图这种点击
TabBar中间
Button时present(模态)出控制器,而点击
TabBar其它的
Button则是苹果默认的直接切换视图的方式,现在很多APP都在使用,特别是直播APP,基本都把直播端模块放在这,最近在仿喵播时正好做到这,就想在网上找现成的框架,结果一直没找到能满足这种需求的框架,就自己动手写了一个,没有仔细打磨算不上框架,但绝对简单好用!
自定义
TabBarController实现原理很简单,无非是用自定义的
Button替换掉苹果自带的
TabBar上的
Button,一般目的是想
TabBar上方显示按钮图片,下面是文字;也就是每个
Button下面有一个
Label。实现这些的重点是计算
Button和
Label的宽度和X坐标值。
下面是JFTabBarController代码实现:
1、 新建三个类:
JFTabBar继承自UIview
JFTabBarButton继承自UIButton
JFTabBarController继承自UITabBarController
2、具体代码:
JFTabBar.h
#import <UIKit/UIKit.h> @class JFTabBar; @protocol JFTabBarDelegate <NSObject> @optional - (void)tabBar:(JFTabBar *)tabBar didSelectedButtonFrom:(int)from to:(int)to; @end @interface JFTabBar : UIView - (void)addTabBarButtonWithItem:(UITabBarItem *)item; - (void)customTheMiddleButtonWithImageName:(NSString *)imageName; @property (nonatomic, weak) id<JFTabBarDelegate> delegate; @end
JFTabBar.m
#import "JFTabBar.h" #import "JFTabBarButton.h" //中间按钮被点击的通知 //此通知需要在JFTabBarController中监听 static NSString * const JFTabBarClickMiddleButtonDidNotification = @"JFTabBarClickMiddleButtonDidNotification"; @interface JFTabBar(){ CGFloat _buttonW; } @property (nonatomic, weak) JFTabBarButton *selectedButton; @property (nonatomic, strong) UIButton *middleButton; @end @implementation JFTabBar - (void)addTabBarButtonWithItem:(UITabBarItem *)item { JFTabBarButton *button = [[JFTabBarButton alloc] init]; [self addSubview:button]; button.item = item; [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchDown]; if (self.subviews.count == 1) { [self buttonClick:button]; } } - (void)buttonClick:(JFTabBarButton *)button { if ([self.delegate respondsToSelector:@selector(tabBar:didSelectedButtonFrom:to:)]) { [self.delegate tabBar:self didSelectedButtonFrom:(int)self.selectedButton.tag to:(int)button.tag]; } self.selectedButton.selected = NO; button.selected = YES; self.selectedButton = button; } /** * self.subviews.count + 1 这里加1是将button的width按三个button计算,实际上是两个button(如果不想present就不需要加1,下面两个if判断也可以去掉) * 两个if判断:1、是将button的x坐标按三个button计算;2、tag值回归正常,不然无法正常切换控制器 * 如你需要添加更多的控制器,这里就需要你自己计算,然后修改以上两点 */ - (void)layoutSubviews { [super layoutSubviews]; CGFloat buttonH = self.frame.size.height; _buttonW = self.frame.size.width / (self.subviews.count + 1); CGFloat buttonY = 0; for (int index = 0; index < self.subviews.count; index++) { JFTabBarButton *button = self.subviews[index]; if (index == 1) index ++; CGFloat buttonX = index * _buttonW; button.frame = CGRectMake(buttonX, buttonY, _buttonW, buttonH); if (index == 2) index --; button.tag = index; } [self customTheMiddleButtonWithImageName:@"toolbar_live"]; } //自定义中间button按钮 - (void)customTheMiddleButtonWithImageName:(NSString *)imageName { // 将Button居中 CGFloat middleButtonX = self.center.x - _buttonW / 2; _middleButton = [[UIButton alloc] initWithFrame:CGRectMake(middleButtonX, 0, _buttonW, self.frame.size.height)]; [_middleButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal]; [_middleButton addTarget:self action:@selector(didClickedMiddleButton:) forControlEvents:UIControlEventTouchDown]; [self addSubview:_middleButton]; } - (void)didClickedMiddleButton:(UIButton *)sender { //注册中间button被点击通知 [[NSNotificationCenter defaultCenter] postNotificationName:JFTabBarClickMiddleButtonDidNotification object:self]; } @end
JFTabBarButton.h
#import <UIKit/UIKit.h> @interface JFTabBarButton : UIButton @property (nonatomic, strong) UITabBarItem *item; @end
JFTabBarButton.m
static const double JFTabBarButtonImageRatio = 0.8; #import "JFTabBarButton.h" @implementation JFTabBarButton - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.imageView.contentMode = UIViewContentModeCenter; self.titleLabel.textAlignment = NSTextAlignmentCenter; self.titleLabel.font = [UIFont systemFontOfSize:11]; [self setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; } return self; } - (void)setHighlighted:(BOOL)highlighted {} - (CGRect)imageRectForContentRect:(CGRect)contentRect{ CGFloat imageW = contentRect.size.width; CGFloat imageH = contentRect.size.height * JFTabBarButtonImageRatio; return CGRectMake(0, 10, imageW, imageH); } //Button下需要文字时打开 //- (CGRect)titleRectForContentRect:(CGRect)contentRect { // CGFloat titleY = contentRect.size.height * JFTabBarButtonImageRatio; // CGFloat titleW = contentRect.size.width; // CGFloat titleH = contentRect.size.height - titleY; // return CGRectMake(0, titleY, titleW, titleH); //} - (void)setItem:(UITabBarItem *)item { _item = item; //Button下需要文字时打开 // [item addObserver:self forKeyPath:@"title" options:0 context:nil]; [item addObserver:self forKeyPath:@"image" options:0 context:nil]; [item addObserver:self forKeyPath:@"selectedImage" options:0 context:nil]; [self observeValueForKeyPath:nil ofObject:nil change:nil context:nil]; } - (void)dealloc { //Button下需要文字时打开 // [self.item removeObserver:self forKeyPath:@"title"]; [self.item removeObserver:self forKeyPath:@"image"]; [self.item removeObserver:self forKeyPath:@"selectedImage"]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // [self setTitle:self.item.title forState:UIControlStateSelected]; // [self setTitle:self.item.title forState:UIControlStateNormal]; [self setImage:self.item.image forState:UIControlStateNormal]; [self setImage:self.item.selectedImage forState:UIControlStateSelected]; } @end
JFTabBarController.h
在
- (void)addAllChildViewControllers中添加除中间那个你需要present(模态)出的控制器
#import <UIKit/UIKit.h> extern NSString * const JFTabBarClickMiddleButtonDidNotification; @interface JFTabBarController : UITabBarController @end
JFTabBarController.m
#import "JFTabBarController.h" #import "JFTabBar.h" #import "JFDisplayViewController.h" #import "JFMeViewController.h" #import "JFLiveViewController.h" @interface JFTabBarController ()<JFTabBarDelegate> @property (nonatomic, weak) JFTabBar *customTabBar; @end @implementation JFTabBarController - (void)viewDidLoad { [super viewDidLoad]; [self customTabBarUI]; // 添加子控制器 [self addAllChildViewControllers]; // 监听中间按钮点击事件 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(presentLiveController) name:@"JFTabBarClickMiddleButtonDidNotification" object:nil]; } // 移除原生的TabBar - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; for (UIView *childView in self.tabBar.subviews) { if ([childView isKindOfClass:[UIControl class]]) { [childView removeFromSuperview]; } } } - (void)customTabBarUI { JFTabBar *customTabBar = [[JFTabBar alloc] init]; customTabBar.frame = self.tabBar.bounds; customTabBar.delegate = self; [self.tabBar addSubview:customTabBar]; self.customTabBar = customTabBar; } - (void)tabBar:(JFTabBar *)tabBar didSelectedButtonFrom:(int)from to:(int)to{ self.selectedIndex = to; } // 下面换成你自己需要添加的控制器就好,只添加除中间需要present(模态)出的控制器。 - (void)addAllChildViewControllers { JFDisplayViewController *displayVC = [[JFDisplayViewController alloc] init]; [self addChildViewController:displayVC title:@"视频" imageName:@"toolbar_home" selectedImageName:@"toolbar_home_sel"]; JFMeViewController *meVC = [[JFMeViewController alloc] init]; [self addChildViewController:meVC title:@"个人" imageName:@"toolbar_me" selectedImageName:@"toolbar_me_sel"]; } - (void)addChildViewController:(UIViewController *)childViewController title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName { childViewController.title = title; childViewController.tabBarItem.image = [UIImage imageNamed:imageName]; childViewController.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:childViewController]; [self addChildViewController:navigationController]; [self.customTabBar addTabBarButtonWithItem:childViewController.tabBarItem]; } //接收到点击中间按钮的通知,present(模态)出控制器 - (void)presentLiveController { JFLiveViewController *jfLiveVC = [[JFLiveViewController alloc] init]; [self presentViewController:jfLiveVC animated:YES completion:nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } // 移除通知 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } @end
说了这么多,如果你也只是需要三个控制器,其实你只需要做这些:
1、下载JFTabBarController源码,解压将JFTabBarController文件夹中文件直接拖入你的xcode项目工程中。
2、在
AppDelegate.m文件中
JFTabBarController设为
window的根控制器。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = [[JFTabBarController alloc] init]; [self.window makeKeyAndVisible]; return YES; }
3、重写
JFTabBarcontroller.m文件中
-(void)addAllChildViewControllers函数,添加子控制器
4、
JFTabBarClickMiddleButtonDidNotification通知,
重写
JFTabBarcontroller.m文件中
- (void)presentLiveController方法。
你需要做的就这四步!
相关文章推荐
- iOS开发导航控制器下不同视图控制器之间切换:利用CATrasition和view的layer层来实现自定义的动画效果
- iOS开发之自定义控制器切换
- IOS开发—自定义导航控制器
- iOS开发Push和Present混用返回指定控制器
- iOS 控制器自定义动画跳转方法(模态跳转)
- IOS开发—IOS自定义任意位置右滑POP视图控制器
- iOS开发--iOS使用自定义URL实现控制器之间的跳转(DCURLRouter组件)
- iOS开发之自定义多控制器的切换
- iOS开发之Present ViewController Modally --弹出模态ViewController
- iOS开发>学无止境 - 自定义控制器转场动画及实现下拉菜单的小Demo
- IOS开发基础05(导航视图控制器,跳转视图控制器,模态)
- IOS开发学习笔记(导航控制器,视图控制器,模态)
- iOS - 控制器自定义动画跳转 [模态跳转]
- IOS开发之——自定义导航控制器
- ios 开发--使用模态跳转了2次之后怎么从第三个视图控制器回到跟视图控制器
- [IOS 开发] 利用Runtime自定义控制器POP手势动画
- 【iOS开发-24】导航控制器下不同视图控制器之间切换:利用CATrasition和view的layer层来实现自定义的动画效果
- IOS开发(19)IOS 自定义UIView实现请求等待控件(模态效果)
- iOS开发之Present ViewController Modally --弹出模态ViewController
- IOS 开发之操作图库自定义控制器