需求如下 效果图
思路
这个需求是,通过切换标签来切换不同的页面,如果在一个controller管理这些view,代码的耦合度就很高。
我就想到了,通过addChildViewController来管理。首先创建一个APTabBarVC继承UITabBarController
- 将这不同的vc添加到Controller的ChildViewController,建立父子关系,可以通过parentViewController访问vc的父类,调用addChildViewController方法.
- 创建首页、应用、数据、我的VC 将首页VC与UINavigationController结合的方式initWithRootViewController。
- 中间那个+号 作为占位用。
直接将这个VC addChildViewController中。
中间按钮的Button是通过继承UITabBar,进行重构实现的。
具体实现如下
添加自定义子控制器的方法
@implementation APTabBarVC
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self addChildViewControllers];
}
- (void)selectAppListMenu{
[self setSelectedIndex:1];
}
- (void)addChildViewControllers{
[self addChildViewController:[[APPortalVC alloc] init] andTitle:@"首页" andImageName:@"sc_tabbar_portal_noselected" addSelectImage:@"sc_tabbar_portal_selected" tag:1000];
[self addChildViewController:[[APAppListVC alloc] init] andTitle:@"应用" andImageName:@"sc_tabbar_app_noselected" addSelectImage:@"sc_tabbar_app_selected" tag:1001];
[self addChildViewController:[[APAppDataDisplayVC alloc] init] andTitle:@"数据" andImageName:@"sc_tabbar_data_noselected" addSelectImage:@"sc_tabbar_data_selected" tag:1002];
[self addChildViewController:[[APUserVC alloc] init] andTitle:@"我的" andImageName:@"sc_tabbar_me_noselected" addSelectImage:@"sc_tabbar_me_selected" tag:1003];
self.tabBar.tintColor = [UIColor blackColor];
}
- (void)addChildViewController:(UIViewController *)childVC andTitle:(NSString *)title andImageName:(NSString *)imageName addSelectImage:(NSString *)selectedImaga tag:(NSInteger)tag{
childVC.tabBarItem.image = [UIImage imageNamed:imageName];
childVC.tabBarItem.selectedImage = [UIImage imageNamed:selectedImaga];
childVC.title = title;
childVC.tabBarItem.tag = tag;
UINavigationController *baseNav = [[UINavigationController alloc] initWithRootViewController:childVC];
[self addChildViewController:baseNav];
}
效果图如下:
如果想要在tabbar上面增加一个按钮(注意!!!不是item,tabBarItem是图片在上,文字在下的格式),产品需求的这个按钮和item样式不一样,占据了和item上文字加图片的大小。由于添加到tabbar上面的item是从左到右的顺序排列的,如果是直接添加一个item,那么不能达到我们想要的效果,这个时候,我们就要考虑通过自定义tabbar来实现。
效果图如下:
- 由于tabber是read-only属性,所以只能通过KVC模式更换tabbar
@property(nonatomic,readonly) UITabBar *tabBar NS_AVAILABLE_IOS(3_0); // Provided for -[UIActionSheet showFromTabBar:]. Attempting to modify the contents of the tab bar directly will throw an exception.
具体实现步骤:
- 创建一个继承自UITabbar的类
- 添加一个UIButton属性。
- 然后设置centerX坐标
代码如下:
#import "APTabBar.h"
@implementation APTabBar
- (instancetype)init{
if (self = [super init]) {
[self initView];
}
return self;
}
- (void)initView{
self.centerBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[self.centerBtn setFrame:CGRectMake(([UIScreen mainScreen].bounds.size.width-46)/2.0, 3, 46, 46)];
[self.centerBtn setImage:[UIImage imageNamed:@"sc_portal_tabbar_add_btn"] forState:UIControlStateNormal];
[self.centerBtn setBackgroundColor:[UIColor whiteColor]];
self.centerBtn.layer.cornerRadius = self.centerBtn.frame.size.height/2;
self.centerBtn.adjustsImageWhenHighlighted = NO;
[self addSubview:self.centerBtn];
}
@end
在APTabBarVC中增加这一段代码,就可以实现效果图的效果了。
self.centerNav = [[UINavigationController alloc] initWithRootViewController:[UIViewController new]];
[self addChildViewController:self.centerNav];
点击中间的按钮 会弹出一个视图效果如下:
再次点击×图片 视图关闭。
具体实现如下:
-自定义一个继承UIView的视图
- 创建一个UICollectionView和cancleBtn
- 实现cancleBtn的回调
- 设置数据源dataArrayM用于展示开门、提报、扫码等
APTabBarCenterPresentView
代码如下:
@interface APTabBarCenterCollectionCell:UICollectionViewCell
@property (nonatomic, strong) UIButton *btn;
@property (nonatomic, strong) UILabel *titleLabel;
@end
@implementation APTabBarCenterCollectionCell
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self addSubViews];
[self setupFrame];
}
return self;
}
- (void)addSubViews{
[self.contentView addSubview:self.btn];
[self.contentView addSubview:self.titleLabel];
}
- (void)setupFrame{
self.btn.frame = CGRectMake(self.frame.size.width/2, 20, 40, 40);
self.titleLabel.frame = CGRectMake(0, self.btn.frame.size.height, self.frame.size.width, 25);
}
#pragma mark 填充数据
- (void)setCellWithModel{
self.titleLabel.text = @"开门";
[self.btn setImage:[UIImage imageNamed:@""] forState:UIControlStateNormal];
}
- (UIButton *)btn{
if (!_btn) {
_btn = [UIButton buttonWithType:UIButtonTypeCustom];
_btn.backgroundColor = [UIColor whiteColor];
[_btn setTitle:@"+" forState:UIControlStateNormal];
[_btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_btn.layer.cornerRadius = 20;
_btn.titleLabel.font = [UIFont systemFontOfSize:35];
_btn.userInteractionEnabled = NO;
}
return _btn;
}
- (UILabel *)titleLabel{
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.textColor = [UIColor grayColor];
_titleLabel.textAlignment = NSTextAlignmentCenter;
}
return _titleLabel;
}
@end
@interface APTabBarCenterPresentView()<UICollectionViewDelegate,UICollectionViewDataSource>
@property (nonatomic, strong)UIButton *cancelBtn;
@property (nonatomic, strong)UICollectionView *collectionView;
@end
@implementation APTabBarCenterPresentView
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self addSubViews];
[self setupFrame];
}
return self;
}
- (void)addSubViews{
//毛玻璃的效果
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
effectView.alpha = 0.9;
effectView.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
[self addSubview:effectView];
[self addSubview:self.collectionView];
[self addSubview:self.cancelBtn];
self.collectionView.backgroundColor = [UIColor clearColor];
}
- (void)setDataArrayM:(NSMutableArray *)dataArrayM{
_dataArrayM = dataArrayM;
[self.collectionView reloadData];
}
- (void)setupFrame{
self.collectionView.frame = CGRectMake(0, 10, self.frame.size.width, self.frame.size.width/3);
self.cancelBtn.frame = CGRectMake(self.frame.size.width/2-20, self.frame.size.height-60, 40, 40);
}
- (void)cancleAction{
self.cancleBlock?self.cancleBlock():nil;
}
#pragma mark 懒加载
- (UIButton *)cancelBtn{
if (!_cancelBtn) {
_cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_cancelBtn setImage:[UIImage imageNamed:@""] forState:UIControlStateNormal];
[_cancelBtn addTarget:self action:@selector(cancleAction) forControlEvents:UIControlEventTouchUpInside];
[_cancelBtn setTitle:@"×" forState:UIControlStateNormal];
_cancelBtn.titleLabel.font = [UIFont systemFontOfSize:20];
_cancelBtn.layer.cornerRadius = 20;
_cancelBtn.layer.backgroundColor = [UIColor lightGrayColor].CGColor;
_cancelBtn.layer.borderWidth = 1;
_cancelBtn.backgroundColor = [UIColor whiteColor];
}
return _cancelBtn;
}
- (UICollectionView *)collectionView{
if (!_collectionView) {
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.minimumLineSpacing = 0;
flowLayout.minimumInteritemSpacing = 0;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.delegate = self;
_collectionView.dataSource = self;
[_collectionView registerClass:APTabBarCenterCollectionCell.class forCellWithReuseIdentifier:@"APTabBarCenterCollectionCell"];
}
return _collectionView;
}
//设置分区数
- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.dataArrayM.count;
}
//设置返回每个item的属性
- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
APTabBarCenterCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"APTabBarCenterCollectionCell" forIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor clearColor];
return cell;
}
//已经选中某个item时触发的方法
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
if (self.dataArrayM.count > indexPath.row) {
self.addBlock?self.addBlock():nil;
}
}
//是否可以选中某个Item,返回NO,则不能选中
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
//通过调整inset使单元格顶部和底部都有间距(inset次序: 上,左,下,右边)
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
//设置每个单元格的大小
- (CGSize)collection:(UICollectionView *)collection layout:(nonnull UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(nonnull NSIndexPath *)indexPath{
return CGSizeMake(self.frame.size.width/3, self.frame.size.width/3);
}
@end
APTabBarVC
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.centerBar = [[APTabBar alloc] init];
[self.centerBar.centerBtn addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
self.centerBar.tintColor = [UIColor redColor];
self.centerBar.translucent = NO;
[self setValue:self.centerBar forKey:@"tabBar"];
self.delegate = self;
[self addChildViewControllers];
[self.view addSubview:self.presentView];
NSMutableArray *presentApplist = [NSMutableArray array];
NSArray *list;
list = @[@{@"title":@"开门",@"color":@"0x6D9FFF",@"action":@"goRemoteOpenDoorAction",@"icon":@"sc_portal_openDoor"},
@{@"title":@"扫码",@"color":@"0xF89656",@"action":@"scanInspectionDeviceQRCode",@"icon":@"sc_portal_scan"},];
[presentApplist addObjectsFromArray:list];
self.presentView.dataArrayM = presentApplist;
__weak __typeof(&*self)weakSelf = self;
self.presentView.addBlock = ^{
__strong __typeof(&*weakSelf)strongSelf = weakSelf;
strongSelf.presentView.hidden = YES;
};
}
在这个方法里面addChildViewControllers 增加
self.centerNav = [[UINavigationController alloc] initWithRootViewController:[UIViewController new]];
[self addChildViewController:self.centerNav];
懒加载
- (void)buttonAction:(UIButton *)button{
self.presentView.hidden = NO;
[self.view bringSubviewToFront:self.presentView];
}
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item{
if (item.tag<=0) {
[self buttonAction:nil];
}
}
- (APTabBarCenterPresentView *)presentView{
if (!_presentView) {
_presentView = [[APTabBarCenterPresentView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height-250, self.view.frame.size.width, 250)];
_presentView.hidden = YES;
__weak __typeof(&*self)weakSelf = self;
_presentView.cancleBlock = ^{
__strong __typeof(&*weakSelf)strongSelf = weakSelf;
strongSelf.presentView.hidden = YES;
};
}
return _presentView;
}
最后效果就是这样