您的位置:首页 > 移动开发 > IOS开发

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
方法。

你需要做的就这四步!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: