Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support centered bottomTab icons using bottomTabs.titleDisplayMode option #5667

Merged
merged 7 commits into from
Nov 24, 2019
Merged
1 change: 1 addition & 0 deletions lib/ios/RNNBottomTabsOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
@property (nonatomic, strong) Text* currentTabId;
@property (nonatomic, strong) Text* barStyle;
@property (nonatomic, strong) Text* fontFamily;
@property (nonatomic, strong) Text* titleDisplayMode;

@end
1 change: 1 addition & 0 deletions lib/ios/RNNBottomTabsOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ - (instancetype)initWithDict:(NSDictionary *)dict {
self.currentTabId = [TextParser parse:dict key:@"currentTabId"];
self.barStyle = [TextParser parse:dict key:@"barStyle"];
self.fontFamily = [TextParser parse:dict key:@"fontFamily"];
self.titleDisplayMode = [TextParser parse:dict key:@"titleDisplayMode"];

return self;
}
Expand Down
1 change: 1 addition & 0 deletions lib/ios/RNNBottomTabsPresenter.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ - (void)applyOptionsOnInit:(RNNNavigationOptions *)options {
UITabBarController *bottomTabs = self.boundViewController;
RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
[bottomTabs setCurrentTabIndex:[withDefault.bottomTabs.currentTabIndex getWithDefaultValue:0]];
[bottomTabs setTabItemImagesCentered:[[withDefault.bottomTabs.titleDisplayMode getWithDefaultValue:@"alwaysShow"] isEqualToString:@"alwaysHide"]];
}

- (void)applyOptions:(RNNNavigationOptions *)options {
Expand Down
6 changes: 6 additions & 0 deletions lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
390AD478200F499D00A8250D /* RNNSwizzles.m in Sources */ = {isa = PBXBuildFile; fileRef = 390AD476200F499D00A8250D /* RNNSwizzles.m */; };
4534E72520CB6724009F8185 /* RNNLargeTitleOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4534E72320CB6724009F8185 /* RNNLargeTitleOptions.h */; };
4534E72620CB6724009F8185 /* RNNLargeTitleOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4534E72420CB6724009F8185 /* RNNLargeTitleOptions.m */; };
5008641223856A2D00A55BE9 /* UITabBar+centered.m in Sources */ = {isa = PBXBuildFile; fileRef = 5008641023856A2C00A55BE9 /* UITabBar+centered.m */; };
501214C9217741A000435148 /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 501214C8217741A000435148 /* libOCMock.a */; };
501223D72173590F000F5F98 /* RNNStackPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 501223D52173590F000F5F98 /* RNNStackPresenter.h */; };
501223D82173590F000F5F98 /* RNNStackPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 501223D62173590F000F5F98 /* RNNStackPresenter.m */; };
Expand Down Expand Up @@ -399,6 +400,8 @@
390AD476200F499D00A8250D /* RNNSwizzles.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSwizzles.m; sourceTree = "<group>"; };
4534E72320CB6724009F8185 /* RNNLargeTitleOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNLargeTitleOptions.h; sourceTree = "<group>"; };
4534E72420CB6724009F8185 /* RNNLargeTitleOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNLargeTitleOptions.m; sourceTree = "<group>"; };
5008641023856A2C00A55BE9 /* UITabBar+centered.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UITabBar+centered.m"; sourceTree = "<group>"; };
5008641123856A2D00A55BE9 /* UITabBar+centered.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UITabBar+centered.h"; sourceTree = "<group>"; };
501214C8217741A000435148 /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOCMock.a; sourceTree = "<group>"; };
501223D52173590F000F5F98 /* RNNStackPresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNStackPresenter.h; sourceTree = "<group>"; };
501223D62173590F000F5F98 /* RNNStackPresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNStackPresenter.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -733,6 +736,8 @@
50706E6C20CE7CA5003345C3 /* UIImage+tint.m */,
506317A8220B547400B26FC3 /* UIImage+insets.h */,
506317A9220B547400B26FC3 /* UIImage+insets.m */,
5008641123856A2D00A55BE9 /* UITabBar+centered.h */,
5008641023856A2C00A55BE9 /* UITabBar+centered.m */,
5038A372216CDDB6009280BC /* UIViewController+SideMenuController.h */,
5038A373216CDDB6009280BC /* UIViewController+SideMenuController.m */,
5038A3BF216E1E66009280BC /* RNNFontAttributesCreator.h */,
Expand Down Expand Up @@ -1604,6 +1609,7 @@
501224072173592D000F5F98 /* RNNBottomTabsPresenter.m in Sources */,
50A00C38200F84D6000F01A6 /* RNNOverlayOptions.m in Sources */,
5039559C2174867000B0A663 /* DoubleParser.m in Sources */,
5008641223856A2D00A55BE9 /* UITabBar+centered.m in Sources */,
E5F6C3A822DB4D0F0093C2CE /* UIView+Utils.m in Sources */,
5049593F216F5D73006D2B81 /* BoolParser.m in Sources */,
50EB93421FE14A3E00BD8EEE /* RNNBottomTabOptions.m in Sources */,
Expand Down
16 changes: 16 additions & 0 deletions lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ - (void)testApplyOptions_shouldApplyOptions {
[self.boundViewController verify];
}

- (void)testApplyOptionsOnInit_alwaysShow_shouldNotCenterTabImages {
RNNNavigationOptions *initialOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
initialOptions.bottomTabs.titleDisplayMode = [[Text alloc] initWithValue:@"alwaysShow"];
[[self.boundViewController expect] setTabItemImagesCentered:NO];
[self.uut applyOptionsOnInit:initialOptions];
[self.boundViewController verify];
}

- (void)testApplyOptions_shouldApplyOptionsOnInit_alwaysHide_shouldCenterTabImages {
RNNNavigationOptions *initialOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
initialOptions.bottomTabs.titleDisplayMode = [[Text alloc] initWithValue:@"alwaysHide"];
[[self.boundViewController expect] setTabItemImagesCentered:YES];
[self.uut applyOptionsOnInit:initialOptions];
[self.boundViewController verify];
}

- (void)testViewDidLayoutSubviews_appliesBadgeOnNextRunLoop {
id uut = [self uut];
[[uut expect] applyDotIndicator];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import <XCTest/XCTest.h>
#import <OCMockObject.h>
#import <OCMock/OCMock.h>
#import "UITabBarController+RNNOptions.h"
#import "UITabBar+centered.h"

@interface UITabBarController_RNNOptionsTest : XCTestCase

Expand All @@ -13,6 +14,7 @@ @implementation UITabBarController_RNNOptionsTest
- (void)setUp {
[super setUp];
self.uut = [OCMockObject partialMockForObject:[UITabBarController new]];
OCMStub([self.uut tabBar]).andReturn([OCMockObject partialMockForObject:[UITabBar new]]);
}

- (void)test_tabBarTranslucent_true {
Expand All @@ -39,6 +41,18 @@ - (void)test_tabBarHideShadow_false {
XCTAssertFalse(self.uut.tabBar.clipsToBounds);
}

- (void)test_setTabItemImagesCentered_true {
[[(id)self.uut.tabBar expect] centerTabItems];
[self.uut setTabItemImagesCentered:YES];
[(id)self.uut.tabBar verify];
}

- (void)test_setTabItemImagesCentered_false {
[[(id)self.uut.tabBar reject] centerTabItems];
[self.uut setTabItemImagesCentered:NO];
[(id)self.uut.tabBar verify];
}

- (void)test_tabBarBackgroundColor {
UIColor* tabBarBackgroundColor = [UIColor redColor];

Expand Down
7 changes: 7 additions & 0 deletions lib/ios/UITabBar+centered.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#import <UIKit/UIKit.h>

@interface UITabBar (centered)

- (void)centerTabItems;

@end
53 changes: 53 additions & 0 deletions lib/ios/UITabBar+centered.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#import "UITabBar+centered.h"
yogevbd marked this conversation as resolved.
Show resolved Hide resolved
#import <objc/runtime.h>

#define BADGE_OFFSET 0.2
#define IMAGE_VIEW_TAG 1

typedef void (*UITabBarButton_layoutSubviews__IMP)(void);
static UITabBarButton_layoutSubviews__IMP original_UITabBarButton_layoutSubviews;

@implementation UITabBar (centered)

- (void)centerTabItems {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[[self class] rnn_extendsUITabBarButtonLayoutSubviews];
});

for (UITabBarItem* item in self.items) {
item.title = nil;
}
}

- (void)rnn_UITabBarButton_layoutSubviews {
yogevbd marked this conversation as resolved.
Show resolved Hide resolved
original_UITabBarButton_layoutSubviews();
for (UIView *subView in self.subviews) {
if ([subView isKindOfClass:NSClassFromString(@"UITabBarSwappableImageView")]) {
subView.center = CGPointMake(subView.center.x, subView.superview.frame.size.height / 2);
subView.tag = IMAGE_VIEW_TAG;
}

if ([subView isKindOfClass:NSClassFromString(@"_UIBadgeView")]) {
UIView* imageView = [subView.superview viewWithTag:IMAGE_VIEW_TAG];
subView.frame = CGRectMake(subView.frame.origin.x, (imageView.frame.origin.y + imageView.frame.size.height * BADGE_OFFSET) - subView.frame.size.height / 2, subView.frame.size.width, subView.frame.size.height);
}
}
}

+ (void)rnn_extendsUITabBarButtonLayoutSubviews {
yogevbd marked this conversation as resolved.
Show resolved Hide resolved
Class UITabBarButtonClass = NSClassFromString(@"UITabBarButton");

SEL layoutSubviewsSEL = @selector(layoutSubviews);
Method layoutSubviewsMethod = class_getInstanceMethod(UITabBarButtonClass, layoutSubviewsSEL);
IMP layoutSubviewsIMP = method_getImplementation(layoutSubviewsMethod);

original_UITabBarButton_layoutSubviews = layoutSubviewsIMP;

SEL rnn_UITabBarButton_layoutSubviewsSEL = @selector(rnn_UITabBarButton_layoutSubviews);
Method rnn_UITabBarButton_layoutSubviewsMethod = class_getInstanceMethod(self, rnn_UITabBarButton_layoutSubviewsSEL);

method_exchangeImplementations(layoutSubviewsMethod, rnn_UITabBarButton_layoutSubviewsMethod);
}

@end
2 changes: 2 additions & 0 deletions lib/ios/UITabBarController+RNNOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@

- (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated;

- (void)setTabItemImagesCentered:(BOOL)centered;

@end
7 changes: 7 additions & 0 deletions lib/ios/UITabBarController+RNNOptions.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#import "UITabBarController+RNNOptions.h"
#import "RNNBottomTabsController.h"
#import "UITabBar+centered.h"

@implementation UITabBarController (RNNOptions)

Expand Down Expand Up @@ -74,6 +75,12 @@ - (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated {
}
}

- (void)setTabItemImagesCentered:(BOOL)centered {
yogevbd marked this conversation as resolved.
Show resolved Hide resolved
if (centered) {
[self.tabBar centerTabItems];
}
}

- (void)forEachTab:(void (^)(UIView *, UIViewController * tabViewController, int tabIndex))performOnTab {
int tabIndex = 0;
for (UIView * tab in self.tabBar.subviews) {
Expand Down