自定义中间按钮可旋转可突出视图Tabbar

前言

小编最近在开发过程中遇到一个这样的需求,就是需要tabbar中间的按钮突出原来的视图,并且中间按钮可以根据需要旋转,废话不多说,先上效果图:


自定义中间按钮可旋转可突出视图Tabbar_第1张图片

如何实现

1.自定义tabbar样式

建立一个类继承UITabBar,并在这个类中设置中间按钮的样式,如下:

#import 

@interface TabBar : UITabBar
@property(nonatomic, strong) UIButton *centerBtn;//中间按钮
@end
//---------------------------------------------------------------
#import "TabBar.h"

@implementation TabBar

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self initView];
    }
    return self;
}

- (void)initView
{
    _centerBtn = [UIButton buttonWithType:UIButtonTypeCustom];
//    设定button大小为适应图片
    UIImage *normalImage = [UIImage imageNamed:@"加"];

    _centerBtn.frame = CGRectMake((UIScreen.mainScreen.bounds.size.width - normalImage.size.width)/2, 0, normalImage.size.width, normalImage.size.height);
    [_centerBtn setImage:normalImage forState:UIControlStateNormal];
    
//    去除选择时高亮
    _centerBtn.adjustsImageWhenHighlighted = NO;
//---------------------------根据需要选择是否保留和设置-------------------------------
//    调整图片突出的位置
    _centerBtn.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width - normalImage.size.width)/2.0, - normalImage.size.height/2.0, normalImage.size.width, normalImage.size.height);
//    给按钮设置边框
//    _centerBtn.layer.masksToBounds = YES;
//    _centerBtn.layer.cornerRadius = _centerBtn.frame.size.width / 2;
//    _centerBtn.layer.borderWidth = 5;
//    _centerBtn.layer.borderColor = [UIColor whiteColor].CGColor;
    
    CGFloat borderWidth = 5;
    UIView *btnLayerView = [[UIView alloc]initWithFrame:(CGRect){_centerBtn.frame.origin.x - borderWidth, _centerBtn.frame.origin.y - borderWidth, _centerBtn.frame.size.width + 2 * borderWidth, _centerBtn.frame.size.height + 2 * borderWidth}];
    btnLayerView.backgroundColor = [UIColor whiteColor];
    btnLayerView.layer.masksToBounds = YES;
    btnLayerView.layer.cornerRadius = btnLayerView.frame.size.width / 2;
    [self addSubview:btnLayerView];
//------------------------------------------------------------------------------
    [self addSubview:_centerBtn];
//    去除Tabbar上方黑线
    [self setBackgroundImage:[self ChangeUIColorToUIImage:[UIColor whiteColor]]];
    [self setShadowImage:[self ChangeUIColorToUIImage:[UIColor whiteColor]]];
}
#pragma mark 颜色转化为图片
- (UIImage *)ChangeUIColorToUIImage: (UIColor *) color
{
    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);
    
    UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return theImage;
}
}
@end

因为按钮有一部分是突出来的,所以需要判定一下,如下:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (self.hidden) {
        return [super hitTest:point withEvent:event];
    }else {
//        转换坐标
        CGPoint tempPoint = [self.centerBtn convertPoint:point fromView:self];
//        判断点击的点是否在按钮区域内
        if (CGRectContainsPoint(self.centerBtn.bounds, tempPoint)) {
//            返回按钮
            return _centerBtn;
        }else {
            return [super hitTest:point withEvent:event];
        }
    }
}

2.添加子视图

建立一个TabbarController继承UITabBarController,将需要展示的子视图添加进去,如下:

#import "TabBarController.h"
#import "TabBar.h"
@interface TabBarController ()
@property (nonatomic, strong) TabBar *tabbar;
@property (assign, nonatomic) BOOL isAnimation;
@end

@implementation TabBarController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self loadUI];
    self.delegate = self;
    _isAnimation = NO;
}
- (void)loadUI {
    _tabbar = [TabBar new];
    [_tabbar.centerBtn addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
//    选中时的颜色
    [self setValue:_tabbar forKey:@"tabBar"];
    
    [self loadViewControllers];
}

- (void)loadViewControllers {
//    中间为设置的图片视图
    NSArray *titles = @[@"Title1",@"Title2",@"",@"Title3",@"Title4"];
    NSMutableArray *clts = [NSMutableArray array];
    for (int i = 0; i < titles.count; i++) {
        UIViewController *vc = [UIViewController new];
        vc.title = titles[i];
//------------------------------根据需求设置Tabbar其他iTem格式--------------------------------
        [vc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor grayColor], NSFontAttributeName:[UIFont systemFontOfSize:13]} forState:UIControlStateNormal];
        [vc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor colorWithRed:18/255.0 green:150/255.0 blue:219/255.0 alpha:1], NSFontAttributeName:[UIFont systemFontOfSize:13]} forState:UIControlStateSelected];
        vc.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, -15);
        CGFloat red = (arc4random() % 255) / 255.0;
        CGFloat green = (arc4random() % 255) / 255.0;
        CGFloat blue = (arc4random() % 255) / 255.0;
        vc.view.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1];
//----------------------------------------------------------------------------------------
        [clts addObject:vc];
    }
    self.viewControllers = clts;
}

3.添加动画

给tabbar的中间按钮添加动画,这个步骤需要绑定tabbar的代理,如下:

- (void)buttonAction:(UIButton *)button {
    self.selectedIndex = 2;//关联中间按钮
    if ([_tabbar.centerBtn.layer.animationKeys containsObject:@"key"] && _isAnimation == YES) {
        [self pauseAnimationInCurrentState:YES];
    }else {
        [self rotationAnimation];
    }
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
    if (tabBarController.selectedIndex != 2 && _isAnimation == YES){//选中中间的按钮
        [self pauseAnimationInCurrentState:YES];
    }
}
//旋转动画
- (void)rotationAnimation{
//    继续旋转
    if ([_tabbar.centerBtn.layer.animationKeys containsObject:@"key"]) {
        CFTimeInterval pauseTime = _tabbar.centerBtn.layer.timeOffset;
        CFTimeInterval begin = CACurrentMediaTime() - pauseTime;
        
        [_tabbar.centerBtn.layer setTimeOffset:0];
        [_tabbar.centerBtn.layer setBeginTime:begin];
        
        _tabbar.centerBtn.layer.speed = 1;
        
    }else {
//        开始旋转
        CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        rotationAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2.0];
        rotationAnimation.duration = 2.0;
        rotationAnimation.repeatCount = HUGE;
        [_tabbar.centerBtn.layer addAnimation:rotationAnimation forKey:@"key"];
    }
    _isAnimation = YES;
}

/**
 暂停动画
 @param isCurrent 是否暂停到当前状态
 */
- (void)pauseAnimationInCurrentState:(BOOL)isCurrent{
    if (isCurrent) {
        //1.取出当前时间,转成动画暂停的时间
        CFTimeInterval pauseTime = [_tabbar.centerBtn.layer convertTime:CACurrentMediaTime() fromLayer:nil];
        
        //2.设置动画的时间偏移量,指定时间偏移量的目的是让动画定格在该时间点的位置
        _tabbar.centerBtn.layer.timeOffset = pauseTime;
        
        //3.将动画的运行速度设置为0, 默认的运行速度是1.0
        _tabbar.centerBtn.layer.speed = 0;

    }else {
        [_tabbar.centerBtn.layer removeAllAnimations];
    }
    _isAnimation = NO;
}

当上述所有步骤都完成之后,大功告成。即可出现上面显示的效果。

希望这篇文章对各位看官有所帮助,Demo下载地址:Demo

你可能感兴趣的:(自定义中间按钮可旋转可突出视图Tabbar)