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 |