iOS修改TabBar的badge的位置

886 阅读1分钟

我们都知道角标是系统的,一般也不会去改,但是公司设计就觉得角标离的位置有点远,要有部分重叠那种。

image.png

我想到的实现方法两种,一种是自定义TabBar,另外一种是不用系统的badge,直接创建一个label盖在上面即可。

我试验了第二种方法,因为第一种改的代码有点多,再加上我们的tabbar还涉及到点击动画效果。

实现方法:

.h文件:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UITabBar (badge)
@property (nonatomic, strong) UILabel *badgeLabel;
- (void)setupBadgeLabel;
- (void)showBadgeOnItemIndex:(int)index withNum:(NSInteger)badgeNum;
- (void)hideBadgeOnItemIndex:(NSInteger)index;

@end

NS_ASSUME_NONNULL_END

.m文件:

#import "UITabBar+badge.h"
#import <objc/runtime.h>

static void * kBadgeLabel = &kBadgeLabel;
#define TabbarBadge_Tag 1000

@implementation UITabBar (badge)

@dynamic badgeLabel;

- (UILabel *)badgeLabel {
    return objc_getAssociatedObject(self, kBadgeLabel);
}

- (void)setBadgeLabel:(UILabel *)badgeLabel {
    return objc_setAssociatedObject(self, kBadgeLabel, badgeLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)setupBadgeLabel {
    //新建小红点
    if (self.badgeLabel == nil) {
        self.badgeLabel = [[UILabel alloc]init];
        self.badgeLabel.font = [UIFont systemFontOfSize:11];
        self.badgeLabel.tag = TabbarBadge_Tag;
        self.badgeLabel.layer.masksToBounds = YES;
        self.badgeLabel.layer.cornerRadius = 8;//圆形
        self.badgeLabel.backgroundColor = [UIColor redColor];//颜色:红色
        self.badgeLabel.textColor = [UIColor whiteColor];
        self.badgeLabel.adjustsFontSizeToFitWidth = YES;
        self.badgeLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:self.badgeLabel];
    }
}

//显示小红点
- (void)showBadgeOnItemIndex:(int)index withNum:(NSInteger)badgeNum {
    //移除之前的小红点
//    [self removeBadgeOnItemIndex:index];
    self.badgeLabel.hidden = NO;
    NSString *badge = (badgeNum > 99?@"99+":[NSString stringWithFormat:@"%ld",badgeNum]);
    //新建小红点
//    UILabel *numLabel = [[UILabel alloc]init];
//    numLabel.font = [UIFont systemFontOfSize:11];
//    numLabel.tag = 888 + index;
//    numLabel.layer.masksToBounds = YES;
//    numLabel.layer.cornerRadius = 8;//圆形
//    numLabel.backgroundColor = [UIColor redColor];//颜色:红色
    CGRect tabFrame = self.frame;

    //确定小红点的位置
    CGFloat itemWidth = tabFrame.size.width / self.items.count;
    CGFloat x = ceil(index * itemWidth + (itemWidth / 2.0));
    CGFloat y = ceilf(0.1 * tabFrame.size.height) - 5;
    
    CGRect rect = [badge boundingRectWithSize:CGSizeMake(MAXFLOAT, 16) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:11]} context:nil];
    self.badgeLabel.frame = CGRectMake(x, y, (rect.size.width > 22) ? rect.size.width : 22, 16);
    self.badgeLabel.text = badge;
    [self bringSubviewToFront:self.badgeLabel];
}

//隐藏小红点
- (void)hideBadgeOnItemIndex:(NSInteger)index {
    //移除小红点
    [self removeBadgeOnItemIndex:index];
}

//移除小红点
- (void)removeBadgeOnItemIndex:(NSInteger)index {
    //按照tag值进行移除
    for (UIView *subView in self.subviews) {
        if (subView.tag == TabbarBadge_Tag) {
//            [subView removeFromSuperview];
            [subView setHidden:YES];
        }
    }
}

@end

PS:因为一开始是每次调用showBadgeOnItemIndex方法,展示badge的时候创建Label,隐藏红点的时候remove。在想会不会性能不太好,只创建一次Label,展示和隐藏就好了。借助到runtime即可。