UITabBarController(三)自定义UITabBar方式二

自定义UITabBar

本文参考至:[iOS 自定义 UITabBar 的样式]http://www.jianshu.com/p/fcf0f6933ffe

自定义以下控件类:

  • 自定义UIButton(图标与文字垂直居中显示)
  • 自定义View放置Tab选项
  • 自定义UITabBar覆盖原有的视图内容
  • 自定义UITabBarController,添加相关逻辑及子视图

自定义UIButton

主要将原有的layout方法改写

自定义VerticalCenterButton类的代码具体如下:

-(void)layoutSubviews
{
    [super layoutSubviews];

    // 图片居中
    CGPoint center = self.imageView.center;
    center.x = self.frame.size.width/2;
    center.y = self.imageView.frame.size.height/2+5;
    self.imageView.center = center;

    // 文字居中
    CGRect newFrame = [self titleLabel].frame;
    newFrame.origin.x = 0;
    newFrame.origin.y = CGRectGetMaxY(self.imageView.frame) + 2;
    newFrame.size.width = self.frame.size.width;
    self.titleLabel.frame = newFrame;
    self.titleLabel.textAlignment = NSTextAlignmentCenter;
    self.titleLabel.font = [UIFont systemFontOfSize:12];
}

自定义放置Tab新内容的View

该View中放置了四个上下垂直显示的Button,以及中间显示一个图标的Button,需要与自定义的UITabBarController进行事件联动,故声明代理。

自定义TabBarView具体代码,如下:

@class TabBarView;
@protocol TabBarViewDelegate <NSObject>
- (void)tabBarView:(TabBarView *)view didSelectItemAtIndex:(NSInteger)index;
- (void)tabBarViewDidClickCenterItem:(TabBarView *)view;
@end

@interface TabBarView : UIView
@property (nonatomic, weak) id<TabBarViewDelegate> viewDelegate;
@end

实现代码如下:

首先,声明内部使用的控件

@interface WDYTabBarView ()
// 背景图片
@property (nonatomic, strong) UIImageView *tabBgView;
// 当前选中的位置
@property (nonatomic, assign) NSInteger selectIndex;
// 图片名称列表
@property (nonatomic, strong) NSArray *imageNameList; 
// 标题类别            
@property (nonatomic, strong) NSArray *titleList;    
// 上次选中的按钮             
@property (nonatomic, strong) WDYVerticalCenterButton *lastItem;  
// 中间图标按钮
@property (nonatomic, strong) UIButton *centerItem;    
@end

其次,将各个属性进行实例化:

// 将各个属性进行懒加载实例化

- (UIImageView *)tabBgView
{
    if (_tabBgView == nil) {
        _tabBgView = [[UIImageView alloc] initWithImage:[UIImage new]];
    }
    return _tabBgView;
}

- (NSArray *)imageNameList
{
    if (_imageNameList == nil) {
        _imageNameList = @[@"tab_live", @"tab_following", @"tab_near", @"tab_me"];
    }
    return _imageNameList;
}
- (NSArray *)titleList
{
    if (_titleList == nil) {
        _titleList = @[@"首页", @"直播", @"附近", @"我的"];
    }
    return _titleList;
}
- (UIButton *)centerItem
{
    if (!_centerItem) {
        _centerItem = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 90, 90)];
        [_centerItem setImage:[UIImage imageNamed:@"tab_launch"] forState:UIControlStateNormal];

        [_centerItem addTarget:self action:@selector(clickItem:) forControlEvents:UIControlEventTouchUpInside];
    }
    return _centerItem;
}

再者,重写init方法:

-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // 加载背景
        [self addSubview:self.tabBgView];
        // 加载item
        for (int i=0; i<self.imageNameList.count; i++) {
            WDYVerticalCenterButton *item = [WDYVerticalCenterButton buttonWithType:UIButtonTypeCustom];
            item.adjustsImageWhenHighlighted = NO;
            [item setImage:[UIImage imageNamed:self.imageNameList[i]] forState:UIControlStateNormal];
            [item setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%@_p",self.imageNameList[i]]] forState:UIControlStateSelected];
            [item setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%@_p",self.imageNameList[i]]] forState:UIControlStateHighlighted];
            [item setTitle:self.titleList[i] forState:UIControlStateNormal];
            [item setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
            [item addTarget:self action:@selector(clickItem:) forControlEvents:UIControlEventTouchUpInside];
            item.tag = i;
            if (i==0) {
                item.selected = YES;
                self.lastItem = item;
            }
            [self addSubview:item];
        }
        [self addSubview:self.centerItem];
    }
    return self;
}

重写,layoutSubviews方法:

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.backgroundColor = [UIColor whiteColor];
    // 把 tabBarButton 取出来
    NSMutableArray *tabBarBtnArr = [NSMutableArray array];
    for (UIView *view in self.subviews) {
        if ([view isKindOfClass:NSClassFromString(@"WDYVerticalCenterButton")]) {
            [tabBarBtnArr addObject:view];
        }
    }

    CGFloat barWidth = self.bounds.size.width;
    CGFloat barHeight = self.bounds.size.height;
    CGFloat centerBtnWidth = CGRectGetWidth(self.centerItem.frame);
    NSLog(@"%f", centerBtnWidth);
    CGFloat centerBtnHeight = CGRectGetHeight(self.centerItem.frame);
    // 设置中间按钮的位置,居中,部分凸起
    self.centerItem.center = CGPointMake(barWidth/2, barHeight - centerBtnWidth/2 + 10);
    [self addSubview:self.centerItem];
    // 重新布局其他 tabBarItem
    // 平均分配其他 tabBarItem 的宽度
    CGFloat barItemWidth = (barWidth - centerBtnWidth) / tabBarBtnArr.count;
    // 逐个布局 tabBarItem, 修改 UITabBarButton 的 frame
    [tabBarBtnArr enumerateObjectsUsingBlock:^(UIView * _Nonnull view, NSUInteger idx, BOOL * _Nonnull stop) {
        CGRect frame = view.frame;
        if (idx >= tabBarBtnArr.count / 2) {
            // 重新设置 x 坐标, 如果排在中间按钮的右边需要加上中间按钮的宽度
            frame.origin.x = idx * barItemWidth + centerBtnWidth;
        } else {
            frame.origin.x = idx * barItemWidth;
        }
        // 重新设置宽度
        frame.size.width = barItemWidth;
        frame.size.height = barHeight;
        view.frame = frame;
    }];
    // 把中间按钮带到视图最前面
    [self bringSubviewToFront:self.centerItem];
}

重写hiteTest:withEvent:方法

// 凸起button原本是接收不到点击事件的,需要重写 hitTest:withEvent: 方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (self.clipsToBounds || self.hidden || (self.alpha == 0.f)) {
        return nil;
    }
    UIView *result = [super hitTest:point withEvent:event];
    // 如果事件发生在tabbar里面直接返回
    if (result) {
        return result;
    }
    // 这里遍历那些超出的部分就可以了,不过这么写比较通用。
    for (UIView *subview in self.subviews) {
        // 吧这个坐标从tabbar的坐标系转为 subview 的坐标系
        CGPoint subPoint = [subview convertPoint:point fromView:self];
        result = [subview hitTest:subPoint withEvent:event];
        // 如果事件发生在 subview 里就返回
        if (result) {
            return result;
        }
    }
    return nil;
}

添加clickItem:方法

- (void)clickItem:(UIButton *)button
{
    if (self.lastItem.tag == button.tag) {
        return;
    }

    if ([button isKindOfClass:[WDYVerticalCenterButton class]]) {
        // 调用代理,切换视图控制器
        [self.viewDelegate wdyTabBarView:self didSelectItemAtIndex:button.tag];
        // **上次选中按钮和本次点击按样式切换在此设置**
        self.selectIndex = button.tag;
        button.selected = YES;
        self.lastItem.selected = NO;
        self.lastItem = (WDYVerticalCenterButton*)button;
        // 动画效果
        [UIView animateWithDuration:0.3 animations:^{
            button.imageView.transform = CGAffineTransformMakeScale(1.2, 1.2);
        } completion:^(BOOL finished) {
            [UIView animateWithDuration:0.3 animations:^{
                button.imageView.transform = CGAffineTransformIdentity;
            }];
        }];
    } else {
        [self.viewDelegate wdyTabBarViewDidClickCenterItem:self];
    }
}

自定义UITabBar

注:本UITabBar主要是将之前自定义的TabBarView用来替换已有的tabBar。

声明部分:

@interface TabBarCustomer : UITabBar
@property (nonatomic, strong) TabBarView *tabBarView;
@end

实现部分:

- (TabBarView *)tabBarView
{
    if (!_tabBarView) {
        _tabBarView = [[TabBarView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 49)];
    }
    return _tabBarView;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addSubview:self.tabBarView];
    }
    return self;
}
-(void)layoutSubviews
{
    [super layoutSubviews];
    // 设置 tabBarView 的 frame
    self.tabBarView.frame = self.bounds;
    // 把 tabbarView 带到最前面, 覆盖 tabbar 的内容
    [self bringSubviewToFront:self.tabBarView];
}
// 凸起button原本是接收不到点击事件的,需要重写 hitTest:withEvent: 方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (self.clipsToBounds || self.hidden || (self.alpha == 0.f)) {
        return nil;
    }
    UIView *result = [super hitTest:point withEvent:event];
    // 如果事件发生在tabbar里面直接返回
    if (result) {
        return result;
    }
    // 这里遍历那些超出的部分就可以了,不过这么写比较通用。
    for (UIView *subview in self.subviews) {
        // 吧这个坐标从tabbar的坐标系转为 subview 的坐标系
        CGPoint subPoint = [subview convertPoint:point fromView:self];
        result = [subview hitTest:subPoint withEvent:event];
        // 如果事件发生在 subview 里就返回
        if (result) {
            return result;
        }
    }
    return nil;
}

自定义UITabBarController

这里设置新的UITabBar,并实现代理方法

自定义UITabBarController的实现代码如下:

// 点击中间图标按钮
-(void)wdyTabBarViewDidClickCenterItem:(WDYTabBarView *)view
{
    NSLog(@"点击中间部分");
}
// 子视图的切换
- (void)wdyTabBarView:(WDYTabBarView *)view didSelectItemAtIndex:(NSInteger)index
{
    NSLog(@"选择-----");
    self.selectedIndex = index;
}

- (void)addAllChildViewController
{
    UIViewController *homeVc = [[UIViewController alloc] init];
    homeVc.view.backgroundColor = [UIColor redColor];
    UIViewController *liveVc = [[UIViewController alloc] init];
    liveVc.view.backgroundColor = [UIColor darkGrayColor];
    UIViewController *searchVc = [[UIViewController alloc] init];
    searchVc.view.backgroundColor = [UIColor whiteColor];
    UIViewController *meVc = [[UIViewController alloc] init];
    meVc.view.backgroundColor = [UIColor lightGrayColor];

    NSMutableArray *arr = [NSMutableArray arrayWithObjects:homeVc, liveVc, searchVc, meVc, nil];
    self.viewControllers = arr;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // 利用KVO来使用自定义的tabBar
    TabBarCustomer *custTabBar = [[TabBarCustomer alloc] init];
    custTabBar.tabBarView.viewDelegate = self;
    [self setValue:custTabBar forKey:@"tabBar"];
    [self addAllChildViewController];
}

在AppDelegate中添加相关代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    self.tabBarController = [[TabBarCtrl alloc] init];
    self.window.rootViewController = self.tabBarController;
    // 设置tabBar每个item选中时的颜色
    [[UITabBar appearance] setTintColor:[UIColor redColor]];
    // 设置这个窗口有主窗口并显示
    [self.window makeKeyAndVisible];
    return YES;
}

实现效果如下:

这里写图片描述![这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值