前言
小编最近在开发过程中遇到一个这样的需求,就是需要tabbar中间的按钮突出原来的视图,并且中间按钮可以根据需要旋转,废话不多说,先上效果图:
如何实现
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