使用KVO实现UITabBar中间按钮放大的方法
.h文件实现
#import <UIKit/UIKit.h>
//进入弹层状态的通知
static NSString *AlivcNotificationQuPlay_EnterMask = @"AlivcNotificationQuPlay_EnterMask";
//退出弹层状态的通知
static NSString *AlivcNotificationQuPlay_QutiMask = @"AlivcNotificationQuPlay_QutiMask";
@class AlivcShortVideoTabBar;
NS_ASSUME_NONNULL_BEGIN
@interface AlivcShortVideoTabBar : UITabBar
/**
中间凸起的按钮
*/
@property (nonatomic, strong) UIButton *centerBtn;
@end
NS_ASSUME_NONNULL_END
.m文件实现方法
#import "AlivcShortVideoTabBar.h"
@interface AlivcShortVideoTabBar ()
/**
生成的用于回调的barItem,认准tag101
*/
@property (nonatomic, strong) UITabBarItem *centerItem;
@end
@implementation AlivcShortVideoTabBar
- (UIButton *)centerBtn
{
if (_centerBtn == nil) {
_centerBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 60)];
[_centerBtn setImage:[AlivcImage imageNamed:@"alivc_svHome_add"] forState:UIControlStateNormal];
[_centerBtn setImage:[AlivcImage imageNamed:@"alivc_svHome_addClose"] forState:UIControlStateSelected];
[_centerBtn addTarget:self action:@selector(clickCenterBtn:) forControlEvents:UIControlEventTouchUpInside];
self.centerItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemSearch tag:101];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(quitMask) name:AlivcNotificationQuPlay_QutiMask object:nil];
}
return _centerBtn;
}
- (void)layoutSubviews
{
[super layoutSubviews];
// 把 tabBarButton 取出来(把 tabBar 的 subViews 打印出来就明白了)
NSMutableArray *tabBarButtonArray = [NSMutableArray array];
for (UIView *view in self.subviews) {
if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
[tabBarButtonArray addObject:view];
}
}
CGFloat barWidth = self.bounds.size.width;
CGFloat barHeight = self.bounds.size.height;
CGFloat centerBtnWidth = CGRectGetWidth(self.centerBtn.frame);
CGFloat centerBtnHeight = CGRectGetHeight(self.centerBtn.frame);
// 重新布局其他 tabBarItem
// 平均分配其他 tabBarItem 的宽度
CGFloat barItemWidth = (barWidth - centerBtnWidth) / tabBarButtonArray.count;
// 逐个布局 tabBarItem,修改 UITabBarButton 的 frame
__block CGFloat centerBtn_cx = barHeight / 2;
[tabBarButtonArray enumerateObjectsUsingBlock:^(UIView * _Nonnull view, NSUInteger idx, BOOL * _Nonnull stop) {
CGFloat beside = barItemWidth / 4; //偏移量
CGRect frame = view.frame;
// 只能适应2个item的情况,多个item需要另外改代码
if (idx >= tabBarButtonArray.count / 2) {
// 重新设置 x 坐标,如果排在中间按钮的右边需要加上中间按钮的宽度
frame.origin.x = idx * barItemWidth + centerBtnWidth + beside;
} else {
frame.origin.x = idx * barItemWidth - beside;
}
// 重新设置宽度
frame.size.width = barItemWidth;
view.frame = frame;
centerBtn_cx = view.center.y;
}];
// 设置中间按钮的位置,居中,凸起一丢丢
self.centerBtn.center = CGPointMake(barWidth / 2, centerBtn_cx - 10);
// 把中间按钮带到视图最前面
if (self.centerBtn.superview == nil) {
[self addSubview:self.centerBtn];
}
[self bringSubviewToFront:self.centerBtn];
}
- (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;
}
#pragma mark - UIRespon
- (void)clickCenterBtn:(UIButton *)button{
button.selected = !button.selected;
if (button.selected) {
[[NSNotificationCenter defaultCenter]postNotificationName:AlivcNotificationQuPlay_EnterMask object:nil];
}else{
[[NSNotificationCenter defaultCenter]postNotificationName:AlivcNotificationQuPlay_QutiMask object:nil];
}
}
- (void)quitMask{
self.centerBtn.selected = NO;
}
@end
使用方式
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface AlivcShortVideoQuHomeTabBarController : UITabBarController
@end
NS_ASSUME_NONNULL_END
#import "AlivcShortVideoQuHomeTabBarController.h"
#import "AlivcShortVideoPersonalViewController.h"
#import "AlivcShortVideoPlayViewControler.h"
#import "AlivcShortVideoTabBar.h"
#import "AlivcDefine.h"
@interface AlivcShortVideoQuHomeTabBarController ()
@property (strong, nonatomic) AlivcShortVideoTabBar *customBar;
@end
@implementation AlivcShortVideoQuHomeTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// 利用KVO来使用自定义的tabBar
self.customBar = [[AlivcShortVideoTabBar alloc]init];
[self setValue:[[AlivcShortVideoTabBar alloc] init] forKey:@"tabBar"];
[self addChildVC];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(centerButtonSelectedToNo) name:AlivcNotificationVideoStartPublish object:nil];
}
- (void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
- (void)addChildVC {
self.tabBar.barTintColor = [UIColor whiteColor];
self.tabBar.tintColor = [UIColor whiteColor];
self.tabBar.backgroundImage = [[UIImage alloc] init];
self.tabBar.shadowImage = [[UIImage alloc] init];
AlivcShortVideoPlayViewControler *playVC =
[[AlivcShortVideoPlayViewControler alloc] init];
playVC.tabBarItem.image = [[AlivcImage imageNamed:@"alivc_svHome_icon"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
playVC.tabBarItem.selectedImage = [[AlivcImage imageNamed:@"alivc_svHome_icon_selected"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[self addChildViewController:playVC];
AlivcShortVideoPersonalViewController *personalVC =
[[AlivcShortVideoPersonalViewController alloc] init];
personalVC.tabBarItem.image = [[AlivcImage imageNamed:@"alivc_svHome_me"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
personalVC.tabBarItem.selectedImage = [[AlivcImage imageNamed:@"alivc_svHome_me_selected"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[self addChildViewController:personalVC];
}
- (void)centerButtonSelectedToNo{
self.customBar.centerBtn.selected = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter]postNotificationName:AlivcNotificationQuPlay_QutiMask object:nil];
});
}
#pragma mark -
- (BOOL)shouldAutorotate{
return [self.selectedViewController shouldAutorotate];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return [self.selectedViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
#pragma mark - UITabBarDelegate
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item{
[[NSNotificationCenter defaultCenter]postNotificationName:AlivcNotificationQuPlay_QutiMask object:nil];
}
@end