Add this property on your screen
{
iconCustomColor: 'red',
}| #import "RCCTabBarController.h" | |
| #import "RCCViewController.h" | |
| #import <React/RCTConvert.h> | |
| #import "RCCManager.h" | |
| #import "RCTHelpers.h" | |
| #import <React/RCTUIManager.h> | |
| #import "UIViewController+Rotation.h" | |
| @interface RCTUIManager () | |
| - (void)configureNextLayoutAnimation:(NSDictionary *)config | |
| withCallback:(RCTResponseSenderBlock)callback | |
| errorCallback:(__unused RCTResponseSenderBlock)errorCallback; | |
| @end | |
| @implementation RCCTabBarController | |
| -(UIInterfaceOrientationMask)supportedInterfaceOrientations { | |
| return [self supportedControllerOrientations]; | |
| } | |
| - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController { | |
| id queue = [[RCCManager sharedInstance].getBridge uiManager].methodQueue; | |
| dispatch_async(queue, ^{ | |
| [[[RCCManager sharedInstance].getBridge uiManager] configureNextLayoutAnimation:nil withCallback:^(NSArray* arr){} errorCallback:^(NSArray* arr){}]; | |
| }); | |
| if (tabBarController.selectedIndex != [tabBarController.viewControllers indexOfObject:viewController]) { | |
| NSDictionary *body = @{ | |
| @"selectedTabIndex": @([tabBarController.viewControllers indexOfObject:viewController]), | |
| @"unselectedTabIndex": @(tabBarController.selectedIndex) | |
| }; | |
| [RCCTabBarController sendScreenTabChangedEvent:viewController body:body]; | |
| [[[RCCManager sharedInstance] getBridge].eventDispatcher sendAppEventWithName:@"bottomTabSelected" body:body]; | |
| if ([viewController isKindOfClass:[UINavigationController class]]) { | |
| UINavigationController *navigationController = (UINavigationController*)viewController; | |
| UIViewController *topViewController = navigationController.topViewController; | |
| if ([topViewController isKindOfClass:[RCCViewController class]]) { | |
| RCCViewController *topRCCViewController = (RCCViewController*)topViewController; | |
| topRCCViewController.commandType = COMMAND_TYPE_BOTTOME_TAB_SELECTED; | |
| topRCCViewController.timestamp = [RCTHelpers getTimestampString]; | |
| } | |
| } | |
| } else { | |
| [RCCTabBarController sendScreenTabPressedEvent:viewController body:nil]; | |
| } | |
| return YES; | |
| } | |
| - (UIImage *)image:(UIImage*)image withColor:(UIColor *)color1 | |
| { | |
| UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale); | |
| CGContextRef context = UIGraphicsGetCurrentContext(); | |
| CGContextTranslateCTM(context, 0, image.size.height); | |
| CGContextScaleCTM(context, 1.0, -1.0); | |
| CGContextSetBlendMode(context, kCGBlendModeNormal); | |
| CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height); | |
| CGContextClipToMask(context, rect, image.CGImage); | |
| [color1 setFill]; | |
| CGContextFillRect(context, rect); | |
| UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); | |
| UIGraphicsEndImageContext(); | |
| return newImage; | |
| } | |
| - (instancetype)initWithProps:(NSDictionary *)props children:(NSArray *)children globalProps:(NSDictionary*)globalProps bridge:(RCTBridge *)bridge | |
| { | |
| self = [super init]; | |
| if (!self) return nil; | |
| self.delegate = self; | |
| self.tabBar.translucent = YES; // default | |
| UIColor *buttonColor = nil; | |
| UIColor *iconColor = nil; | |
| UIColor *selectedButtonColor = nil; | |
| UIColor *labelColor = nil; | |
| UIColor *selectedLabelColor = nil; | |
| NSDictionary *tabsStyle = props[@"style"]; | |
| if (tabsStyle) | |
| { | |
| NSString *tabBarButtonColor = tabsStyle[@"tabBarButtonColor"]; | |
| if (tabBarButtonColor) | |
| { | |
| UIColor *color = tabBarButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarButtonColor] : nil; | |
| self.tabBar.tintColor = color; | |
| buttonColor = color; | |
| selectedButtonColor = color; | |
| } | |
| NSString *tabBarSelectedButtonColor = tabsStyle[@"tabBarSelectedButtonColor"]; | |
| if (tabBarSelectedButtonColor) | |
| { | |
| UIColor *color = tabBarSelectedButtonColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarSelectedButtonColor] : nil; | |
| self.tabBar.tintColor = color; | |
| selectedButtonColor = color; | |
| } | |
| NSString *tabBarLabelColor = tabsStyle[@"tabBarLabelColor"]; | |
| if(tabBarLabelColor) { | |
| UIColor *color = tabBarLabelColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarLabelColor] : nil; | |
| labelColor = color; | |
| } | |
| NSString *tabBarSelectedLabelColor = tabsStyle[@"tabBarSelectedLabelColor"]; | |
| if(tabBarLabelColor) { | |
| UIColor *color = tabBarSelectedLabelColor != (id)[NSNull null] ? [RCTConvert UIColor: | |
| tabBarSelectedLabelColor] : nil; | |
| selectedLabelColor = color; | |
| } | |
| NSString *tabBarBackgroundColor = tabsStyle[@"tabBarBackgroundColor"]; | |
| if (tabBarBackgroundColor) | |
| { | |
| UIColor *color = tabBarBackgroundColor != (id)[NSNull null] ? [RCTConvert UIColor:tabBarBackgroundColor] : nil; | |
| self.tabBar.barTintColor = color; | |
| } | |
| NSString *tabBarTranslucent = tabsStyle[@"tabBarTranslucent"]; | |
| if (tabBarTranslucent) | |
| { | |
| self.tabBar.translucent = [tabBarTranslucent boolValue] ? YES : NO; | |
| } | |
| NSString *tabBarHideShadow = tabsStyle[@"tabBarHideShadow"]; | |
| if (tabBarHideShadow) | |
| { | |
| self.tabBar.clipsToBounds = [tabBarHideShadow boolValue] ? YES : NO; | |
| } | |
| } | |
| NSMutableArray *viewControllers = [NSMutableArray array]; | |
| // go over all the tab bar items | |
| for (NSDictionary *tabItemLayout in children) | |
| { | |
| // make sure the layout is valid | |
| if (![tabItemLayout[@"type"] isEqualToString:@"TabBarControllerIOS.Item"]) continue; | |
| if (!tabItemLayout[@"props"]) continue; | |
| // get the view controller inside | |
| if (!tabItemLayout[@"children"]) continue; | |
| if (![tabItemLayout[@"children"] isKindOfClass:[NSArray class]]) continue; | |
| if ([tabItemLayout[@"children"] count] < 1) continue; | |
| NSDictionary *childLayout = tabItemLayout[@"children"][0]; | |
| UIViewController *viewController = [RCCViewController controllerWithLayout:childLayout globalProps:globalProps bridge:bridge]; | |
| if (!viewController) continue; | |
| // create the tab icon and title | |
| NSString *title = tabItemLayout[@"props"][@"title"]; | |
| UIImage *iconImage = nil; | |
| id icon = tabItemLayout[@"props"][@"icon"]; | |
| NSString *iconCustomColor = tabItemLayout[@"props"][@"iconCustomColor"]; | |
| if (iconCustomColor) | |
| { | |
| UIColor *color = iconCustomColor != (id)[NSNull null] ? [RCTConvert UIColor:iconCustomColor] : nil; | |
| iconColor = color; | |
| } | |
| if (icon) | |
| { | |
| iconImage = [RCTConvert UIImage:icon]; | |
| if (iconColor) | |
| { | |
| iconImage = [[self image:iconImage withColor:iconColor] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; | |
| iconColor = buttonColor; | |
| } | |
| else | |
| { | |
| iconImage = [[self image:iconImage withColor:buttonColor] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; | |
| } | |
| } | |
| UIImage *iconImageSelected = nil; | |
| id selectedIcon = tabItemLayout[@"props"][@"selectedIcon"]; | |
| if (selectedIcon) { | |
| iconImageSelected = [RCTConvert UIImage:selectedIcon]; | |
| } else { | |
| iconImageSelected = [RCTConvert UIImage:icon]; | |
| } | |
| viewController.tabBarItem = [[UITabBarItem alloc] initWithTitle:title image:iconImage tag:0]; | |
| viewController.tabBarItem.accessibilityIdentifier = tabItemLayout[@"props"][@"testID"]; | |
| viewController.tabBarItem.selectedImage = iconImageSelected; | |
| id imageInsets = tabItemLayout[@"props"][@"iconInsets"]; | |
| if (imageInsets && imageInsets != (id)[NSNull null]) | |
| { | |
| id topInset = imageInsets[@"top"]; | |
| id leftInset = imageInsets[@"left"]; | |
| id bottomInset = imageInsets[@"bottom"]; | |
| id rightInset = imageInsets[@"right"]; | |
| CGFloat top = topInset != (id)[NSNull null] ? [RCTConvert CGFloat:topInset] : 0; | |
| CGFloat left = topInset != (id)[NSNull null] ? [RCTConvert CGFloat:leftInset] : 0; | |
| CGFloat bottom = topInset != (id)[NSNull null] ? [RCTConvert CGFloat:bottomInset] : 0; | |
| CGFloat right = topInset != (id)[NSNull null] ? [RCTConvert CGFloat:rightInset] : 0; | |
| viewController.tabBarItem.imageInsets = UIEdgeInsetsMake(top, left, bottom, right); | |
| } | |
| NSMutableDictionary *unselectedAttributes = [RCTHelpers textAttributesFromDictionary:tabsStyle withPrefix:@"tabBarText" baseFont:[UIFont systemFontOfSize:10]]; | |
| if (!unselectedAttributes[NSForegroundColorAttributeName] && labelColor) { | |
| unselectedAttributes[NSForegroundColorAttributeName] = labelColor; | |
| } | |
| [viewController.tabBarItem setTitleTextAttributes:unselectedAttributes forState:UIControlStateNormal]; | |
| NSMutableDictionary *selectedAttributes = [RCTHelpers textAttributesFromDictionary:tabsStyle withPrefix:@"tabBarSelectedText" baseFont:[UIFont systemFontOfSize:10]]; | |
| if (!selectedAttributes[NSForegroundColorAttributeName] && selectedLabelColor) { | |
| selectedAttributes[NSForegroundColorAttributeName] = selectedLabelColor; | |
| } | |
| [viewController.tabBarItem setTitleTextAttributes:selectedAttributes forState:UIControlStateSelected]; | |
| // create badge | |
| NSObject *badge = tabItemLayout[@"props"][@"badge"]; | |
| if (badge == nil || [badge isEqual:[NSNull null]]) | |
| { | |
| viewController.tabBarItem.badgeValue = nil; | |
| } | |
| else | |
| { | |
| viewController.tabBarItem.badgeValue = [NSString stringWithFormat:@"%@", badge]; | |
| } | |
| [viewControllers addObject:viewController]; | |
| } | |
| // replace the tabs | |
| self.viewControllers = viewControllers; | |
| NSNumber *initialTab = tabsStyle[@"initialTabIndex"]; | |
| if (initialTab) | |
| { | |
| NSInteger initialTabIndex = initialTab.integerValue; | |
| [self setSelectedIndex:initialTabIndex]; | |
| } | |
| [self setRotation:props]; | |
| return self; | |
| } | |
| - (void)performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams bridge:(RCTBridge *)bridge completion:(void (^)(void))completion | |
| { | |
| if ([performAction isEqualToString:@"setBadge"]) | |
| { | |
| UIViewController *viewController = nil; | |
| NSNumber *tabIndex = actionParams[@"tabIndex"]; | |
| if (tabIndex) | |
| { | |
| int i = (int)[tabIndex integerValue]; | |
| if ([self.viewControllers count] > i) | |
| { | |
| viewController = [self.viewControllers objectAtIndex:i]; | |
| } | |
| } | |
| NSString *contentId = actionParams[@"contentId"]; | |
| NSString *contentType = actionParams[@"contentType"]; | |
| if (contentId && contentType) | |
| { | |
| viewController = [[RCCManager sharedInstance] getControllerWithId:contentId componentType:contentType]; | |
| } | |
| if (viewController) | |
| { | |
| NSObject *badge = actionParams[@"badge"]; | |
| if (badge == nil || [badge isEqual:[NSNull null]]) | |
| { | |
| viewController.tabBarItem.badgeValue = nil; | |
| } | |
| else | |
| { | |
| NSString *badgeColor = actionParams[@"badgeColor"]; | |
| UIColor *color = badgeColor != (id)[NSNull null] ? [RCTConvert UIColor:badgeColor] : nil; | |
| if ([viewController.tabBarItem respondsToSelector:@selector(badgeColor)]) { | |
| viewController.tabBarItem.badgeColor = color; | |
| } | |
| viewController.tabBarItem.badgeValue = [NSString stringWithFormat:@"%@", badge]; | |
| } | |
| } | |
| } | |
| if ([performAction isEqualToString:@"switchTo"]) | |
| { | |
| UIViewController *viewController = nil; | |
| NSNumber *tabIndex = actionParams[@"tabIndex"]; | |
| if (tabIndex) | |
| { | |
| int i = (int)[tabIndex integerValue]; | |
| if ([self.viewControllers count] > i) | |
| { | |
| viewController = [self.viewControllers objectAtIndex:i]; | |
| } | |
| } | |
| NSString *contentId = actionParams[@"contentId"]; | |
| NSString *contentType = actionParams[@"contentType"]; | |
| if (contentId && contentType) | |
| { | |
| viewController = [[RCCManager sharedInstance] getControllerWithId:contentId componentType:contentType]; | |
| } | |
| if (viewController) | |
| { | |
| [self setSelectedViewController:viewController]; | |
| } | |
| } | |
| if ([performAction isEqualToString:@"setTabButton"]) | |
| { | |
| UIViewController *viewController = nil; | |
| NSNumber *tabIndex = actionParams[@"tabIndex"]; | |
| if (tabIndex) | |
| { | |
| int i = (int)[tabIndex integerValue]; | |
| if ([self.viewControllers count] > i) | |
| { | |
| viewController = [self.viewControllers objectAtIndex:i]; | |
| } | |
| } | |
| NSString *contentId = actionParams[@"contentId"]; | |
| NSString *contentType = actionParams[@"contentType"]; | |
| if (contentId && contentType) | |
| { | |
| viewController = [[RCCManager sharedInstance] getControllerWithId:contentId componentType:contentType]; | |
| } | |
| if (viewController) | |
| { | |
| UIImage *iconImage = nil; | |
| id icon = actionParams[@"icon"]; | |
| if (icon && icon != (id)[NSNull null]) | |
| { | |
| iconImage = [RCTConvert UIImage:icon]; | |
| iconImage = [[self image:iconImage withColor:self.tabBar.tintColor] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; | |
| viewController.tabBarItem.image = iconImage; | |
| } | |
| UIImage *iconImageSelected = nil; | |
| id selectedIcon = actionParams[@"selectedIcon"]; | |
| if (selectedIcon && selectedIcon != (id)[NSNull null]) | |
| { | |
| iconImageSelected = [RCTConvert UIImage:selectedIcon]; | |
| viewController.tabBarItem.selectedImage = iconImageSelected; | |
| } | |
| } | |
| } | |
| if ([performAction isEqualToString:@"setTabBarHidden"]) | |
| { | |
| BOOL hidden = [actionParams[@"hidden"] boolValue]; | |
| CGRect nextFrame = self.tabBar.frame; | |
| nextFrame.origin.y = UIScreen.mainScreen.bounds.size.height - (hidden ? 0 : self.tabBar.frame.size.height); | |
| [UIView animateWithDuration: ([actionParams[@"animated"] boolValue] ? 0.45 : 0) | |
| delay: 0 | |
| usingSpringWithDamping: 0.75 | |
| initialSpringVelocity: 0 | |
| options: (hidden ? UIViewAnimationOptionCurveEaseIn : UIViewAnimationOptionCurveEaseOut) | |
| animations:^() | |
| { | |
| [self.tabBar setFrame:nextFrame]; | |
| } | |
| completion:^(BOOL finished) | |
| { | |
| if (completion != nil) | |
| { | |
| completion(); | |
| } | |
| }]; | |
| return; | |
| } | |
| else if (completion != nil) | |
| { | |
| completion(); | |
| } | |
| } | |
| +(void)sendScreenTabChangedEvent:(UIViewController*)viewController body:(NSDictionary*)body{ | |
| [RCCTabBarController sendTabEvent:@"bottomTabSelected" controller:viewController body:body]; | |
| } | |
| +(void)sendScreenTabPressedEvent:(UIViewController*)viewController body:(NSDictionary*)body{ | |
| [RCCTabBarController sendTabEvent:@"bottomTabReselected" controller:viewController body:body]; | |
| } | |
| +(void)sendTabEvent:(NSString *)event controller:(UIViewController*)viewController body:(NSDictionary*)body{ | |
| if ([viewController.view isKindOfClass:[RCTRootView class]]){ | |
| RCTRootView *rootView = (RCTRootView *)viewController.view; | |
| if (rootView.appProperties && rootView.appProperties[@"navigatorEventID"]) { | |
| NSString *navigatorID = rootView.appProperties[@"navigatorID"]; | |
| NSString *screenInstanceID = rootView.appProperties[@"screenInstanceID"]; | |
| NSMutableDictionary *screenDict = [NSMutableDictionary dictionaryWithDictionary:@ | |
| { | |
| @"id": event, | |
| @"navigatorID": navigatorID, | |
| @"screenInstanceID": screenInstanceID | |
| }]; | |
| if (body) { | |
| [screenDict addEntriesFromDictionary:body]; | |
| } | |
| [[[RCCManager sharedInstance] getBridge].eventDispatcher sendAppEventWithName:rootView.appProperties[@"navigatorEventID"] body:screenDict]; | |
| } | |
| } | |
| if ([viewController isKindOfClass:[UINavigationController class]]) { | |
| UINavigationController *navigationController = (UINavigationController*)viewController; | |
| UIViewController *topViewController = [navigationController topViewController]; | |
| [RCCTabBarController sendTabEvent:event controller:topViewController body:body]; | |
| } | |
| } | |
| @end |