ChenYilong / CYLTabBarController

[EN]It is an iOS UI module library for adding animation to iOS tabbar items and icons with Lottie, and adding a bigger center UITabBar Item. [CN]【中国特色 TabBar】一行代码实现 Lottie 动画TabBar,支持中间带+号的TabBar样式,自带红点角标,支持动态刷新。【iOS13 & Dark Mode & iPhone XS MAX supported】
MIT License
6.91k stars 1.45k forks source link

[bug]: 红点不显示 #539

Open make2a opened 3 years ago

make2a commented 3 years ago

红点不显示。

  1. Version:Latest Version as v1.29.0
  2. Language of App :Objective-C
  3. iOS System Version:iOS12
  4. Prototype(是否是真机):YES
  5. Issue Type:Crash、Bug、Enhancement(希望能支持一个新需求)、Q-A

1. How to reproduce the problem.

调用红点代码:

- (void)customizeInterface {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    //    [self.viewControllers[1].tabBarItem cyl_showBadge];
        [self.viewControllers[1] cyl_showBadgeValue:@"" animationType:CYLBadgeAnimationTypeScale];
    });
}

或者:

    [self setViewDidLayoutSubViewsBlockInvokeOnce:YES block:^(CYLTabBarController *tabBarController) {
        NSUInteger delaySeconds = 1.5;
        dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
        dispatch_after(when, dispatch_get_main_queue(), ^{
            @try {
                UIViewController *viewController0 = tabBarController.viewControllers[0];
                // UIControl *tab0 = viewController0.cyl_tabButton;
                // [tab0 cyl_showBadge];
                [viewController0 cyl_setBadgeCenterOffset:CGPointMake(-5, 3)];
                //                [viewController0 cyl_setBadgeRadius:11/2];
                //以上对Badge的参数设置,需要在 cyl_showBadgeValue 调用之前执行。
                [viewController0 cyl_showBadge];

                [tabBarController.viewControllers[1] cyl_showBadgeValue:@"" animationType:CYLBadgeAnimationTypeScale];
                [tabBarController.viewControllers[2] cyl_showBadgeValue:@"" animationType:CYLBadgeAnimationTypeShake];

            } @catch (NSException *exception) {}

            //添加仿淘宝tabbar,第一个tab选中后有图标覆盖
            if (self.selectedIndex != 0) {
                return;
            }
            // tabBarController.selectedIndex = 1;
        });
    }];

都不能显示红点。block都不能触发。

3. Here is a Demo.

//
//  CRTabBarController.m
//  CartoonReader
//
//  Created by lm98 on 6/18/20.
//  Copyright © 2020 boluo. All rights reserved.
//

#import "CRTabBarController.h"
#import "CRMainViewController.h"
#import "CRBookRackViewController.h"
#import "CRMineViewController.h"

static CGFloat const CYLTabBarControllerHeight = 49.f;

@interface CRTabBarController ()

@end

@implementation CRTabBarController

- (instancetype)init {
    if (!(self = [super init])) {
        return nil;
    }
    /**
     * 以下两行代码目的在于手动设置让TabBarItem只显示图标,不显示文字,并让图标垂直居中。
     * 等效于在 `-tabBarItemsAttributesForController` 方法中不传 `CYLTabBarItemTitle` 字段。
     * 更推荐后一种做法。
     */
    UIEdgeInsets imageInsets = UIEdgeInsetsZero;//UIEdgeInsetsMake(4.5, 0, -4.5, 0);
    UIOffset titlePositionAdjustment = UIOffsetMake(0, 0);
    CYLTabBarController *tabBarController = [CYLTabBarController tabBarControllerWithViewControllers:self.viewControllers
                                                                               tabBarItemsAttributes:self.tabBarItemsAttributesForController
                                                                                         imageInsets:imageInsets
                                                                             titlePositionAdjustment:titlePositionAdjustment
                                                                                             context:@""];
    [self customizeTabBarAppearance:tabBarController];
    return (self = (CRTabBarController *)tabBarController);
}

- (NSArray *)viewControllers {

    CRMainViewController *homeVC = [[CRMainViewController alloc] init];
    CRBaseNavigationController *firstNavigationController = [[CRBaseNavigationController alloc]
       initWithRootViewController:homeVC];
    firstNavigationController.navigationBar.translucent = NO;

    CRBookRackViewController *infoVC = [[CRBookRackViewController alloc] init];
    CRBaseNavigationController *thirdNavigationController = [[CRBaseNavigationController alloc]
                                                      initWithRootViewController:infoVC];
    thirdNavigationController.navigationBar.hidden = YES;

    CRMineViewController *myVC = [[CRMineViewController alloc] init];
    CRBaseNavigationController *fourthNavigationController = [[CRBaseNavigationController alloc]
                                                     initWithRootViewController:myVC];

    NSArray *viewControllers = @[
                                 firstNavigationController,
                                 thirdNavigationController,
                                 fourthNavigationController
                                 ];
    return viewControllers;
}

- (NSArray *)tabBarItemsAttributesForController {
    CGFloat firstXOffset = -12/2;
    NSDictionary *firstTabBarItemsAttributes = @{
                                                 CYLTabBarItemTitle : @"首页",
                                                 CYLTabBarItemImage : @"homeAb",  /* NSString and UIImage are supported*/
                                                 CYLTabBarItemSelectedImage : @"homeAa",  /* NSString and UIImage are supported*/
                                                 CYLTabBarItemTitlePositionAdjustment: [NSValue valueWithUIOffset:UIOffsetMake(firstXOffset, 0)],
                                                 CYLTabBarLottieURL : [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"home" ofType:@"json"]],
                                                  CYLTabBarLottieSize: [NSValue valueWithCGSize:CGSizeMake(36, 36)]
                                                 };

    NSDictionary *thirdTabBarItemsAttributes = @{
                                                 CYLTabBarItemTitle : @"书架" ,
                                                 CYLTabBarItemImage : @"bookshelfAb",
                                                 CYLTabBarItemSelectedImage : @"bookshelfAa",
                                                 CYLTabBarItemTitlePositionAdjustment: [NSValue valueWithUIOffset:UIOffsetMake(0, 0)],
                                                 CYLTabBarLottieURL : [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"book" ofType:@"json"]],
                                                 CYLTabBarLottieSize: [NSValue valueWithCGSize:CGSizeMake(36, 36)]
                                                 };

    NSDictionary *thourthTabBarItemsAttributes = @{
                                                 CYLTabBarItemTitle : @"我",
                                                 CYLTabBarItemImage : @"myAb",
                                                 CYLTabBarItemSelectedImage : @"myAa",
                                                 CYLTabBarItemTitlePositionAdjustment: [NSValue valueWithUIOffset:UIOffsetMake(-firstXOffset, 0)],
                                                 CYLTabBarLottieURL : [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"my" ofType:@"json"]],
                                                 CYLTabBarLottieSize: [NSValue valueWithCGSize:CGSizeMake(36, 36)]
                                                 };

    NSArray *tabBarItemsAttributes = @[
                                       firstTabBarItemsAttributes,
                                       thirdTabBarItemsAttributes,
                                       thourthTabBarItemsAttributes
                                       ];
    return tabBarItemsAttributes;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [[UIApplication sharedApplication] setApplicationSupportsShakeToEdit:YES];
    [self becomeFirstResponder];
    self.tabBarController.tabBar.backgroundColor = [UIColor whiteColor];
    [self customizeInterface];

}
- (void)customizeInterface {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.viewControllers[1].tabBarItem cyl_showBadge];
        [self.viewControllers[1] cyl_showBadgeValue:@"" animationType:CYLBadgeAnimationTypeScale];
    });
}
- (void)requestCollectUpdate{
    [CRCartoonVM requestUpdateCollectWithcallBack:^(id  _Nullable data, NSString * _Nonnull code, NSString * _Nonnull msg) {
        BOOL hasUpdate = [data[@"data"][@"has_update"] boolValue];
        if (hasUpdate) {
            //            [self.viewControllers[1] cyl_showBadgeValue:@"2" animationType:CYLBadgeAnimationTypeScale];
        }
    }];
}
/**
 *  更多TabBar自定义设置:比如:tabBarItem 的选中和不选中文字和背景图片属性、tabbar 背景图片属性等等
 */
- (void)customizeTabBarAppearance:(CYLTabBarController *)tabBarController {
    // Customize UITabBar height
    // 自定义 TabBar 高度
    //        tabBarController.tabBarHeight = CYL_IS_IPHONE_X ? 65 : 40;
    [tabBarController rootWindow].backgroundColor = [UIColor whiteColor];

    // set the text color for unselected state
    // 普通状态下的文字属性
    NSMutableDictionary *normalAttrs = [NSMutableDictionary dictionary];
    normalAttrs[NSForegroundColorAttributeName] = getColorA(@"#999999", 1.0);
    normalAttrs[NSFontAttributeName] = FONT_SC_SIZE(10);

    // set the text color for selected state
    // 选中状态下的文字属性
    NSMutableDictionary *selectedAttrs = [NSMutableDictionary dictionary];
    selectedAttrs[NSForegroundColorAttributeName] = getColor(@"#000000");
    selectedAttrs[NSFontAttributeName] = FONT_SC_SIZE(10);

    // set the text Attributes
    // 设置文字属性

    if (@available(iOS 13.0, *)){
        UITabBar *tabBar = [UITabBar appearance];
        [tabBar setTintColor:getColor(@"#000000")];
        [tabBar setUnselectedItemTintColor:getColorA(@"#000000", 0.5)];

    }else{
        UITabBarItem *tabBar = [UITabBarItem appearance];
        [tabBar setTitleTextAttributes:normalAttrs forState:UIControlStateNormal];
        [tabBar setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];
    }

    UIView *line = [[UIView alloc]initWithFrame:CGRectMake(0, -1, SCREEN_WIDTH, 0.5)];
    line.backgroundColor = crLineColor();
    [tabBarController.tabBar addSubview:line];

    // Set the dark color to selected tab (the dimmed background)
    // TabBarItem选中后的背景颜色
   // [self customizeTabBarSelectionIndicatorImage];

    // update TabBar when TabBarItem width did update
    // If your app need support UIDeviceOrientationLandscapeLeft or UIDeviceOrientationLandscapeRight,
    // remove the comment '//'
    // 如果你的App需要支持横竖屏,请使用该方法移除注释 '//'
    //[self updateTabBarCustomizationWhenTabBarItemWidthDidUpdate];

//    // set the bar background image
//    // 设置背景图片
    UITabBar *tabBarAppearance = [UITabBar appearance];
    UIImage *image = imageWithColor([UIColor whiteColor]);
    [tabBarAppearance setBackgroundImage:image];

    //FIXED:  https://github.com/ChenYilong/CYLTabBarController/issues/312
    [UITabBar appearance].translucent = NO;
    //FIXED: https://github.com/ChenYilong/CYLTabBarController/issues/196

//
//    // remove the bar system shadow image
//    // 去除 TabBar 自带的顶部阴影
//    // iOS10 后 需要使用 `-[CYLTabBarController hideTabBadgeBackgroundSeparator]` 见 AppDelegate 类中的演示;
    // iOS13.1 iphoneX机型 上如果设置透明色会失效
    [[UITabBar appearance] setShadowImage:imageWithColor([UIColor whiteColor])];
}

- (void)updateTabBarCustomizationWhenTabBarItemWidthDidUpdate {
    void (^deviceOrientationDidChangeBlock)(NSNotification *) = ^(NSNotification *notification) {
        UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
        if ((orientation == UIDeviceOrientationLandscapeLeft) || (orientation == UIDeviceOrientationLandscapeRight)) {
            NSLog(@"Landscape Left or Right !");
        } else if (orientation == UIDeviceOrientationPortrait) {
            NSLog(@"Landscape portrait!");
        }
        [self customizeTabBarSelectionIndicatorImage];
    };
    [[NSNotificationCenter defaultCenter] addObserverForName:CYLTabBarItemWidthDidChangeNotification
                                                      object:nil
                                                       queue:[NSOperationQueue mainQueue]
                                                  usingBlock:deviceOrientationDidChangeBlock];
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
    return YES;
}

- (void)customizeTabBarSelectionIndicatorImage {
    ///Get initialized TabBar Height if exists, otherwise get Default TabBar Height.
    CGFloat tabBarHeight = CYLTabBarControllerHeight;
    CGSize selectionIndicatorImageSize = CGSizeMake(CYLTabBarItemWidth, tabBarHeight);
    //Get initialized TabBar if exists.
    UITabBar *tabBar = [self cyl_tabBarController].tabBar ?: [UITabBar appearance];
    [tabBar setSelectionIndicatorImage:
     [[self class] imageWithColor:[UIColor whiteColor]
                             size:selectionIndicatorImageSize]];
}

+ (UIImage *)scaleImage:(UIImage *)image {
    CGFloat halfWidth = image.size.width/2;
    CGFloat halfHeight = image.size.height/2;
    UIImage *secondStrechImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(halfHeight, halfWidth, halfHeight, halfWidth) resizingMode:UIImageResizingModeStretch];
    return secondStrechImage;
}

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size {
    if (!color || size.width <= 0 || size.height <= 0) return nil;
    CGRect rect = CGRectMake(0.0f, 0.0f, size.width + 1, size.height);
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, rect);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}
@end

4. Here is my Debug log

image image

self.invokeOnceViewDidLayoutSubViewsBlock = YES 进入 viewDidLayoutSubviews 后变为了NO