效果如图:
image.png
iOS系统自带tabbar是对称的,且不宜控制tabbaritem的位置和大小.而且按钮超出tabbar的部分无法点击.这里想实现如效果图所示的tabbar有两个注意点:
1.tabbarController的tabbar属性是只读,需要用kvc
// 修改系统tabbar
QqLEETabBar *tabbar = [QqLEETabBar new];
[self setValue:tabbar forKeyPath:@"tabBar"];
tabbar.myDelegate = self;
2.在tabbar中复写hitest方法,拦截点击事件交给按钮处理
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
//这一个判断是关键,不判断的话push到其他页面,点击发布按钮的位置也是会有反应的,这样就不好了
//self.isHidden == NO 说明当前页面是有tabbar的,那么肯定是在导航控制器的根控制器页面
//在导航控制器根控制器页面,那么我们就需要判断手指点击的位置是否在发布按钮身上
//是的话让发布按钮自己处理点击事件,不是的话让系统去处理点击事件就可以了
if (self.isHidden == NO) {
//将当前tabbar的触摸点转换坐标系,转换到发布按钮的身上,生成一个新的点
CGPoint newP = [self convertPoint:point toView:self.leftButton];
CGPoint newP1 = [self convertPoint:point toView:self.rightButton];
//判断如果这个新的点是在发布按钮身上,那么处理点击事件最合适的view就是发布按钮
if ( [self.leftButton pointInside:newP withEvent:event]) {
return self.leftButton;
}else if([self.rightButton pointInside:newP1 withEvent:event]){
return self.rightButton;
}
else{//如果点不在发布按钮身上,直接让系统处理就可以了
return [super hitTest:point withEvent:event];
}
}
else {//tabbar隐藏了,那么说明已经push到其他的页面了,这个时候还是让系统去判断最合适的view处理就好了
return [super hitTest:point withEvent:event];
}
}
全部代码如下
1.tabbarcontroller
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface QqHomeTabBarController : UITabBarController
@end
NS_ASSUME_NONNULL_END
#import "QqHomeTabBarController.h"
//#import "QqClassHomeVC.h"
#import "QqHomeVC.h"
#import "QqMyHomeVC.h"
#import "UIImage+QRCode.h"
#import "LEEButton.h"
#import "QqLEETabBar.h"
@interface QqHomeTabBarController ()<QqLEETabBarDelegate>
@end
@implementation QqHomeTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
}
-(void)setupUI{
// 修改系统tabbar
QqLEETabBar *tabbar = [QqLEETabBar new];
[self setValue:tabbar forKeyPath:@"tabBar"];
tabbar.myDelegate = self;
// 增加子控制器
[self addVC:[QqHomeVC new] title:nil image:nil];
[self addVC:[QqMyHomeVC new] title:nil image:nil];
}
-(void)addVC:(UIViewController *)vc title:(NSString *)title image:(NSString *)image{
vc.tabBarItem.title = title;
vc.tabBarItem.image = [UIImage imageNamed:image];
[vc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]} forState:UIControlStateSelected];
[vc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor clearColor]} forState:UIControlStateNormal];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:vc];
[self addChildViewController:nav];
}
-(void)helpSelectIndex:(NSUInteger)index{
self.selectedIndex = index;
}
@end
2.自定义tabbar
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@protocol QqLEETabBarDelegate <NSObject>
-(void)helpSelectIndex:(NSUInteger)index;
@end
@interface QqLEETabBar : UITabBar
/** tabbar的代理 */
@property (nonatomic, weak) id<QqLEETabBarDelegate> myDelegate;
@end
NS_ASSUME_NONNULL_END
#import "QqLEETabBar.h"
#import "LEEButton.h"
@interface QqLEETabBar ()
@property( weak, nonatomic) UIImageView *bgImgView;
@property( weak, nonatomic) LEETabbarButton *rightButton;
@property( weak, nonatomic) LEETabbarButton *leftButton;
@property( weak, nonatomic) UIButton *emptyButton;
@property( strong, nonatomic) LEETabbarButton *selectedButton;
@end
@implementation QqLEETabBar
-(instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
[self setupUI];
}
return self;
}
-(void)setupUI{
// 清空tabbar
[self setBackgroundImage:[UIImage new]];
[self setShadowImage:[UIImage new]];
// tabbar 背景图
UIImageView *bgImgView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"tabbar_bg"]];
bgImgView.contentMode = UIViewContentModeScaleAspectFill ;
[self addSubview:bgImgView];
self.bgImgView = bgImgView;
// 几个按钮
NSString *sexImg = @"女孩-icon未选中";
if ([QqUserInfo sharedInstance].sex == 2) {
}else{
sexImg = @"男孩-icon未选中";
}
LEETabbarButton *rightButton = [LEETabbarButton new];
[rightButton setImage:[UIImage imageNamed:sexImg] forState:UIControlStateNormal];
[self addSubview:rightButton];
[rightButton addTarget:self action:@selector(clickRight:) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTitle:@"我的" forState:UIControlStateNormal];
[rightButton setTitleColor:RGBA(173, 251, 137) forState:UIControlStateNormal];
[rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
rightButton.titleLabel.font = [UIFont systemFontOfSize:10];
self.rightButton = rightButton;
LEETabbarButton *leftButton = [LEETabbarButton new];
[leftButton setImage:[UIImage imageNamed:@"课堂icon 未选中"] forState:UIControlStateNormal];
[self addSubview:leftButton];
[leftButton addTarget:self action:@selector(clickLeft:) forControlEvents:UIControlEventTouchUpInside];
[leftButton setTitle:@"课堂" forState:UIControlStateNormal];
[leftButton setTitleColor:RGBA(173, 251, 137) forState:UIControlStateNormal];
[leftButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
leftButton.titleLabel.font = [UIFont systemFontOfSize:10];
leftButton.selected = YES;
self.leftButton = leftButton;
self.selectedButton = leftButton;
UIButton *emptyButton = [UIButton new];
[self addSubview:emptyButton];
self.emptyButton = emptyButton;
if ([[UIDevice currentDevice].model isEqualToString:@"iPad"]) {
leftButton.titleLabel.font = [UIFont systemFontOfSize:12];
rightButton.titleLabel.font = [UIFont systemFontOfSize:12];
}
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(QqUserInfoChanged) name:QqUserInfoChanged object:nil];
}
-(void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
-(void)layoutSubviews{
[super layoutSubviews];
CGFloat h = self.frame.size.height;
if ([[UIDevice currentDevice].model isEqualToString:@"iPad"]) {
self.bgImgView.image = [UIImage imageNamed:@"tabbar_bg_ipad"];
self.bgImgView.frame = CGRectMake(screenW-458, h-83.5, 458, 83.5);
}else{
self.bgImgView.frame = CGRectMake(screenW-328, h-60, 328, 60);
}
self.rightButton.frame = CGRectMake(screenW-130, h-60, 130, 60);
self.leftButton.frame = CGRectMake(screenW-260, h-60, 130, 60);
self.emptyButton.frame = CGRectMake(0, h-60, screenW-260, 60);
if ([[UIDevice currentDevice].model isEqualToString:@"iPad"]) {
self.rightButton.frame = CGRectMake(screenW-180, h-83, 180, 83);
self.leftButton.frame = CGRectMake(screenW-360, h-83, 180, 83);
self.emptyButton.frame = CGRectMake(0, h-83, screenW-360,83);
}
[self bringSubviewToFront:self.leftButton];
[self bringSubviewToFront:self.rightButton];
[self bringSubviewToFront:self.emptyButton];
}
-(void)clickLeft:(LEETabbarButton *)button{
self.selectedButton.selected = false;
button.selected = YES;
self.selectedButton = button;
[self animateLayer:button.layer];
if (self.myDelegate) {
[self.myDelegate helpSelectIndex:0];
}
}
-(void)clickRight:(LEETabbarButton *)button{
self.selectedButton.selected = false;
button.selected = YES;
self.selectedButton = button;
[self animateLayer:button.layer];
if (self.myDelegate) {
[self.myDelegate helpSelectIndex:1];
}
}
-(void)QqUserInfoChanged{
NSString *img = nil;
if ([QqUserInfo sharedInstance].sex == 2) {
img = @"女孩-icon未选中";
}else{
img = @"男孩-icon未选中";
}
[self.rightButton setImage:[UIImage imageNamed:img] forState:UIControlStateNormal];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
//这一个判断是关键,不判断的话push到其他页面,点击发布按钮的位置也是会有反应的,这样就不好了
//self.isHidden == NO 说明当前页面是有tabbar的,那么肯定是在导航控制器的根控制器页面
//在导航控制器根控制器页面,那么我们就需要判断手指点击的位置是否在发布按钮身上
//是的话让发布按钮自己处理点击事件,不是的话让系统去处理点击事件就可以了
if (self.isHidden == NO) {
//将当前tabbar的触摸点转换坐标系,转换到发布按钮的身上,生成一个新的点
CGPoint newP = [self convertPoint:point toView:self.leftButton];
CGPoint newP1 = [self convertPoint:point toView:self.rightButton];
//判断如果这个新的点是在发布按钮身上,那么处理点击事件最合适的view就是发布按钮
if ( [self.leftButton pointInside:newP withEvent:event]) {
return self.leftButton;
}else if([self.rightButton pointInside:newP1 withEvent:event]){
return self.rightButton;
}
else{//如果点不在发布按钮身上,直接让系统处理就可以了
return [super hitTest:point withEvent:event];
}
}
else {//tabbar隐藏了,那么说明已经push到其他的页面了,这个时候还是让系统去判断最合适的view处理就好了
return [super hitTest:point withEvent:event];
}
}
-(void)animateLayer:(CALayer *)layer{
CABasicAnimation*pulse = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
pulse.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
pulse.duration = 0.08;
pulse.repeatCount= 1;
pulse.autoreverses= YES;
pulse.fromValue= [NSNumber numberWithFloat:0.7];
pulse.toValue= [NSNumber numberWithFloat:1.3];
[layer addAnimation:pulse forKey:nil];
}
@end
网友评论