美文网首页
iOS 自定义tabbar 非对称排列 点击穿透

iOS 自定义tabbar 非对称排列 点击穿透

作者: 后青春期的诗大喵 | 来源:发表于2019-10-23 15:28 被阅读0次

效果如图:


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

相关文章

网友评论

      本文标题:iOS 自定义tabbar 非对称排列 点击穿透

      本文链接:https://www.haomeiwen.com/subject/affdvctx.html