From 4614b053324bae7c8be90f587d3dcfc453f167e4 Mon Sep 17 00:00:00 2001 From: yogevbd Date: Wed, 20 Nov 2019 15:06:02 +0200 Subject: [PATCH 1/3] Support centered bottomTab icons using bottomTabs.titleDisplayMode option --- lib/ios/RNNBottomTabsOptions.h | 1 + lib/ios/RNNBottomTabsOptions.m | 1 + lib/ios/RNNBottomTabsPresenter.m | 1 + .../project.pbxproj | 6 +++ .../RNNTabBarPresenterTest.m | 16 ++++++ .../UITabBarController+RNNOptionsTest.m | 16 +++++- lib/ios/UITabBar+centered.h | 7 +++ lib/ios/UITabBar+centered.m | 53 +++++++++++++++++++ lib/ios/UITabBarController+RNNOptions.h | 2 + lib/ios/UITabBarController+RNNOptions.m | 7 +++ 10 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 lib/ios/UITabBar+centered.h create mode 100644 lib/ios/UITabBar+centered.m diff --git a/lib/ios/RNNBottomTabsOptions.h b/lib/ios/RNNBottomTabsOptions.h index a6b1027c43f..2c39daf8dc8 100644 --- a/lib/ios/RNNBottomTabsOptions.h +++ b/lib/ios/RNNBottomTabsOptions.h @@ -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 diff --git a/lib/ios/RNNBottomTabsOptions.m b/lib/ios/RNNBottomTabsOptions.m index cb040159c27..9478a0e4d81 100644 --- a/lib/ios/RNNBottomTabsOptions.m +++ b/lib/ios/RNNBottomTabsOptions.m @@ -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; } diff --git a/lib/ios/RNNBottomTabsPresenter.m b/lib/ios/RNNBottomTabsPresenter.m index 6ca11edef25..715e85c7d5e 100644 --- a/lib/ios/RNNBottomTabsPresenter.m +++ b/lib/ios/RNNBottomTabsPresenter.m @@ -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 { diff --git a/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj b/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj index dcf99e149fb..55b34d5d9fd 100644 --- a/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj +++ b/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj @@ -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 */; }; @@ -399,6 +400,8 @@ 390AD476200F499D00A8250D /* RNNSwizzles.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSwizzles.m; sourceTree = ""; }; 4534E72320CB6724009F8185 /* RNNLargeTitleOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNLargeTitleOptions.h; sourceTree = ""; }; 4534E72420CB6724009F8185 /* RNNLargeTitleOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNLargeTitleOptions.m; sourceTree = ""; }; + 5008641023856A2C00A55BE9 /* UITabBar+centered.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UITabBar+centered.m"; sourceTree = ""; }; + 5008641123856A2D00A55BE9 /* UITabBar+centered.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UITabBar+centered.h"; sourceTree = ""; }; 501214C8217741A000435148 /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOCMock.a; sourceTree = ""; }; 501223D52173590F000F5F98 /* RNNStackPresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNStackPresenter.h; sourceTree = ""; }; 501223D62173590F000F5F98 /* RNNStackPresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNStackPresenter.m; sourceTree = ""; }; @@ -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 */, @@ -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 */, diff --git a/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m b/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m index 37cda8972a4..ab3c4f8c9e6 100644 --- a/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m +++ b/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m @@ -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]; diff --git a/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m b/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m index 7018286ef26..f9b54db9f16 100644 --- a/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m +++ b/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m @@ -1,6 +1,7 @@ #import -#import +#import #import "UITabBarController+RNNOptions.h" +#import "UITabBar+centered.h" @interface UITabBarController_RNNOptionsTest : XCTestCase @@ -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 { @@ -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]; diff --git a/lib/ios/UITabBar+centered.h b/lib/ios/UITabBar+centered.h new file mode 100644 index 00000000000..fd2ca92c357 --- /dev/null +++ b/lib/ios/UITabBar+centered.h @@ -0,0 +1,7 @@ +#import + +@interface UITabBar (centered) + +- (void)centerTabItems; + +@end diff --git a/lib/ios/UITabBar+centered.m b/lib/ios/UITabBar+centered.m new file mode 100644 index 00000000000..bfe0f3f2fa8 --- /dev/null +++ b/lib/ios/UITabBar+centered.m @@ -0,0 +1,53 @@ +#import "UITabBar+centered.h" +#import + +#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 { + 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 { + 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 diff --git a/lib/ios/UITabBarController+RNNOptions.h b/lib/ios/UITabBarController+RNNOptions.h index 412bb07d9ec..71190a60d64 100644 --- a/lib/ios/UITabBarController+RNNOptions.h +++ b/lib/ios/UITabBarController+RNNOptions.h @@ -18,4 +18,6 @@ - (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated; +- (void)setTabItemImagesCentered:(BOOL)centered; + @end diff --git a/lib/ios/UITabBarController+RNNOptions.m b/lib/ios/UITabBarController+RNNOptions.m index d95f7978b4a..67b2d15ff31 100644 --- a/lib/ios/UITabBarController+RNNOptions.m +++ b/lib/ios/UITabBarController+RNNOptions.m @@ -1,5 +1,6 @@ #import "UITabBarController+RNNOptions.h" #import "RNNBottomTabsController.h" +#import "UITabBar+centered.h" @implementation UITabBarController (RNNOptions) @@ -74,6 +75,12 @@ - (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated { } } +- (void)setTabItemImagesCentered:(BOOL)centered { + if (centered) { + [self.tabBar centerTabItems]; + } +} + - (void)forEachTab:(void (^)(UIView *, UIViewController * tabViewController, int tabIndex))performOnTab { int tabIndex = 0; for (UIView * tab in self.tabBar.subviews) { From 33f2b9af4e15ef9f85dd9a639e81581e8b88c4be Mon Sep 17 00:00:00 2001 From: yogevbd Date: Sun, 24 Nov 2019 15:30:28 +0200 Subject: [PATCH 2/3] Improve readability, better namings --- lib/ios/RNNBottomTabsPresenter.m | 4 +- .../project.pbxproj | 12 ++--- .../RNNTabBarPresenterTest.m | 4 +- .../UITabBarController+RNNOptionsTest.m | 12 ++--- .../{UITabBar+centered.h => UITabBar+utils.h} | 2 +- .../{UITabBar+centered.m => UITabBar+utils.m} | 51 +++++++++++-------- lib/ios/UITabBarController+RNNOptions.h | 2 +- lib/ios/UITabBarController+RNNOptions.m | 8 ++- 8 files changed, 48 insertions(+), 47 deletions(-) rename lib/ios/{UITabBar+centered.h => UITabBar+utils.h} (64%) rename lib/ios/{UITabBar+centered.m => UITabBar+utils.m} (68%) diff --git a/lib/ios/RNNBottomTabsPresenter.m b/lib/ios/RNNBottomTabsPresenter.m index 715e85c7d5e..11e564c9e96 100644 --- a/lib/ios/RNNBottomTabsPresenter.m +++ b/lib/ios/RNNBottomTabsPresenter.m @@ -9,7 +9,9 @@ - (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"]]; + if ([[withDefault.bottomTabs.titleDisplayMode getWithDefaultValue:@"alwaysShow"] isEqualToString:@"alwaysHide"]) { + [bottomTabs setTabItemImagesCentered]; + } } - (void)applyOptions:(RNNNavigationOptions *)options { diff --git a/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj b/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj index 55b34d5d9fd..4455328e10a 100644 --- a/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj +++ b/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj @@ -50,7 +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 */; }; + 5008641223856A2D00A55BE9 /* UITabBar+utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5008641023856A2C00A55BE9 /* UITabBar+utils.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 */; }; @@ -400,8 +400,8 @@ 390AD476200F499D00A8250D /* RNNSwizzles.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSwizzles.m; sourceTree = ""; }; 4534E72320CB6724009F8185 /* RNNLargeTitleOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNLargeTitleOptions.h; sourceTree = ""; }; 4534E72420CB6724009F8185 /* RNNLargeTitleOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNLargeTitleOptions.m; sourceTree = ""; }; - 5008641023856A2C00A55BE9 /* UITabBar+centered.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UITabBar+centered.m"; sourceTree = ""; }; - 5008641123856A2D00A55BE9 /* UITabBar+centered.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UITabBar+centered.h"; sourceTree = ""; }; + 5008641023856A2C00A55BE9 /* UITabBar+utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UITabBar+utils.m"; sourceTree = ""; }; + 5008641123856A2D00A55BE9 /* UITabBar+utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UITabBar+utils.h"; sourceTree = ""; }; 501214C8217741A000435148 /* libOCMock.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libOCMock.a; sourceTree = ""; }; 501223D52173590F000F5F98 /* RNNStackPresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNStackPresenter.h; sourceTree = ""; }; 501223D62173590F000F5F98 /* RNNStackPresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNStackPresenter.m; sourceTree = ""; }; @@ -736,8 +736,8 @@ 50706E6C20CE7CA5003345C3 /* UIImage+tint.m */, 506317A8220B547400B26FC3 /* UIImage+insets.h */, 506317A9220B547400B26FC3 /* UIImage+insets.m */, - 5008641123856A2D00A55BE9 /* UITabBar+centered.h */, - 5008641023856A2C00A55BE9 /* UITabBar+centered.m */, + 5008641123856A2D00A55BE9 /* UITabBar+utils.h */, + 5008641023856A2C00A55BE9 /* UITabBar+utils.m */, 5038A372216CDDB6009280BC /* UIViewController+SideMenuController.h */, 5038A373216CDDB6009280BC /* UIViewController+SideMenuController.m */, 5038A3BF216E1E66009280BC /* RNNFontAttributesCreator.h */, @@ -1609,7 +1609,7 @@ 501224072173592D000F5F98 /* RNNBottomTabsPresenter.m in Sources */, 50A00C38200F84D6000F01A6 /* RNNOverlayOptions.m in Sources */, 5039559C2174867000B0A663 /* DoubleParser.m in Sources */, - 5008641223856A2D00A55BE9 /* UITabBar+centered.m in Sources */, + 5008641223856A2D00A55BE9 /* UITabBar+utils.m in Sources */, E5F6C3A822DB4D0F0093C2CE /* UIView+Utils.m in Sources */, 5049593F216F5D73006D2B81 /* BoolParser.m in Sources */, 50EB93421FE14A3E00BD8EEE /* RNNBottomTabOptions.m in Sources */, diff --git a/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m b/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m index ab3c4f8c9e6..be54d51aac1 100644 --- a/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m +++ b/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m @@ -57,7 +57,7 @@ - (void)testApplyOptions_shouldApplyOptions { - (void)testApplyOptionsOnInit_alwaysShow_shouldNotCenterTabImages { RNNNavigationOptions *initialOptions = [[RNNNavigationOptions alloc] initEmptyOptions]; initialOptions.bottomTabs.titleDisplayMode = [[Text alloc] initWithValue:@"alwaysShow"]; - [[self.boundViewController expect] setTabItemImagesCentered:NO]; + [[self.boundViewController reject] setTabItemImagesCentered]; [self.uut applyOptionsOnInit:initialOptions]; [self.boundViewController verify]; } @@ -65,7 +65,7 @@ - (void)testApplyOptionsOnInit_alwaysShow_shouldNotCenterTabImages { - (void)testApplyOptions_shouldApplyOptionsOnInit_alwaysHide_shouldCenterTabImages { RNNNavigationOptions *initialOptions = [[RNNNavigationOptions alloc] initEmptyOptions]; initialOptions.bottomTabs.titleDisplayMode = [[Text alloc] initWithValue:@"alwaysHide"]; - [[self.boundViewController expect] setTabItemImagesCentered:YES]; + [[self.boundViewController expect] setTabItemImagesCentered]; [self.uut applyOptionsOnInit:initialOptions]; [self.boundViewController verify]; } diff --git a/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m b/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m index f9b54db9f16..b9f36f71c41 100644 --- a/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m +++ b/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m @@ -1,7 +1,7 @@ #import #import #import "UITabBarController+RNNOptions.h" -#import "UITabBar+centered.h" +#import "UITabBar+utils.h" @interface UITabBarController_RNNOptionsTest : XCTestCase @@ -41,15 +41,9 @@ - (void)test_tabBarHideShadow_false { XCTAssertFalse(self.uut.tabBar.clipsToBounds); } -- (void)test_setTabItemImagesCentered_true { +- (void)test_setTabItemImagesCentered { [[(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]; + [self.uut setTabItemImagesCentered]; [(id)self.uut.tabBar verify]; } diff --git a/lib/ios/UITabBar+centered.h b/lib/ios/UITabBar+utils.h similarity index 64% rename from lib/ios/UITabBar+centered.h rename to lib/ios/UITabBar+utils.h index fd2ca92c357..85649a9e2ea 100644 --- a/lib/ios/UITabBar+centered.h +++ b/lib/ios/UITabBar+utils.h @@ -1,6 +1,6 @@ #import -@interface UITabBar (centered) +@interface UITabBar (utils) - (void)centerTabItems; diff --git a/lib/ios/UITabBar+centered.m b/lib/ios/UITabBar+utils.m similarity index 68% rename from lib/ios/UITabBar+centered.m rename to lib/ios/UITabBar+utils.m index bfe0f3f2fa8..1cc04220b4d 100644 --- a/lib/ios/UITabBar+centered.m +++ b/lib/ios/UITabBar+utils.m @@ -1,4 +1,4 @@ -#import "UITabBar+centered.h" +#import "UITabBar+utils.h" #import #define BADGE_OFFSET 0.2 @@ -7,20 +7,42 @@ typedef void (*UITabBarButton_layoutSubviews__IMP)(void); static UITabBarButton_layoutSubviews__IMP original_UITabBarButton_layoutSubviews; -@implementation UITabBar (centered) +@implementation UITabBar (utils) - (void)centerTabItems { + [self removeTabBarItemTitles]; + [self swizzleUITabBarButton]; +} + +- (void)removeTabBarItemTitles { + for (UITabBarItem* item in self.items) { + item.title = nil; + } +} + +- (void)swizzleUITabBarButton { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - [[self class] rnn_extendsUITabBarButtonLayoutSubviews]; + [[self class] swizzleUITabBarButtonLayoutSubviews]; }); +} + ++ (void)swizzleUITabBarButtonLayoutSubviews { + Class UITabBarButtonClass = NSClassFromString(@"UITabBarButton"); - for (UITabBarItem* item in self.items) { - item.title = nil; - } + SEL layoutSubviewsSEL = @selector(layoutSubviews); + Method layoutSubviewsMethod = class_getInstanceMethod(UITabBarButtonClass, layoutSubviewsSEL); + IMP layoutSubviewsIMP = method_getImplementation(layoutSubviewsMethod); + + original_UITabBarButton_layoutSubviews = layoutSubviewsIMP; + + SEL swizzleUITabBarButton_layoutSubviewsSEL = @selector(swizzleUITabBarButton_layoutSubviews); + Method swizzleUITabBarButton_layoutSubviewsMethod = class_getInstanceMethod(self, swizzleUITabBarButton_layoutSubviewsSEL); + + method_exchangeImplementations(layoutSubviewsMethod, swizzleUITabBarButton_layoutSubviewsMethod); } -- (void)rnn_UITabBarButton_layoutSubviews { +- (void)swizzleUITabBarButton_layoutSubviews { original_UITabBarButton_layoutSubviews(); for (UIView *subView in self.subviews) { if ([subView isKindOfClass:NSClassFromString(@"UITabBarSwappableImageView")]) { @@ -35,19 +57,4 @@ - (void)rnn_UITabBarButton_layoutSubviews { } } -+ (void)rnn_extendsUITabBarButtonLayoutSubviews { - 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 diff --git a/lib/ios/UITabBarController+RNNOptions.h b/lib/ios/UITabBarController+RNNOptions.h index 71190a60d64..476fbb3f8f2 100644 --- a/lib/ios/UITabBarController+RNNOptions.h +++ b/lib/ios/UITabBarController+RNNOptions.h @@ -18,6 +18,6 @@ - (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated; -- (void)setTabItemImagesCentered:(BOOL)centered; +- (void)setTabItemImagesCentered; @end diff --git a/lib/ios/UITabBarController+RNNOptions.m b/lib/ios/UITabBarController+RNNOptions.m index 67b2d15ff31..26e6f930701 100644 --- a/lib/ios/UITabBarController+RNNOptions.m +++ b/lib/ios/UITabBarController+RNNOptions.m @@ -1,6 +1,6 @@ #import "UITabBarController+RNNOptions.h" #import "RNNBottomTabsController.h" -#import "UITabBar+centered.h" +#import "UITabBar+utils.h" @implementation UITabBarController (RNNOptions) @@ -75,10 +75,8 @@ - (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated { } } -- (void)setTabItemImagesCentered:(BOOL)centered { - if (centered) { - [self.tabBar centerTabItems]; - } +- (void)setTabItemImagesCentered { + [self.tabBar centerTabItems]; } - (void)forEachTab:(void (^)(UIView *, UIViewController * tabViewController, int tabIndex))performOnTab { From 94b52bdf7563ca68cbb2a444146944dcbd40a38c Mon Sep 17 00:00:00 2001 From: yogevbd Date: Sun, 24 Nov 2019 16:04:59 +0200 Subject: [PATCH 3/3] Rename setTabItemImagesCentered to centerTabItems --- lib/ios/RNNBottomTabsPresenter.m | 2 +- lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m | 4 ++-- .../UITabBarController+RNNOptionsTest.m | 4 ++-- lib/ios/UITabBarController+RNNOptions.h | 2 +- lib/ios/UITabBarController+RNNOptions.m | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/ios/RNNBottomTabsPresenter.m b/lib/ios/RNNBottomTabsPresenter.m index 11e564c9e96..790b7b12c9a 100644 --- a/lib/ios/RNNBottomTabsPresenter.m +++ b/lib/ios/RNNBottomTabsPresenter.m @@ -10,7 +10,7 @@ - (void)applyOptionsOnInit:(RNNNavigationOptions *)options { RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]]; [bottomTabs setCurrentTabIndex:[withDefault.bottomTabs.currentTabIndex getWithDefaultValue:0]]; if ([[withDefault.bottomTabs.titleDisplayMode getWithDefaultValue:@"alwaysShow"] isEqualToString:@"alwaysHide"]) { - [bottomTabs setTabItemImagesCentered]; + [bottomTabs centerTabItems]; } } diff --git a/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m b/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m index be54d51aac1..eeb899413d1 100644 --- a/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m +++ b/lib/ios/ReactNativeNavigationTests/RNNTabBarPresenterTest.m @@ -57,7 +57,7 @@ - (void)testApplyOptions_shouldApplyOptions { - (void)testApplyOptionsOnInit_alwaysShow_shouldNotCenterTabImages { RNNNavigationOptions *initialOptions = [[RNNNavigationOptions alloc] initEmptyOptions]; initialOptions.bottomTabs.titleDisplayMode = [[Text alloc] initWithValue:@"alwaysShow"]; - [[self.boundViewController reject] setTabItemImagesCentered]; + [[self.boundViewController reject] centerTabItems]; [self.uut applyOptionsOnInit:initialOptions]; [self.boundViewController verify]; } @@ -65,7 +65,7 @@ - (void)testApplyOptionsOnInit_alwaysShow_shouldNotCenterTabImages { - (void)testApplyOptions_shouldApplyOptionsOnInit_alwaysHide_shouldCenterTabImages { RNNNavigationOptions *initialOptions = [[RNNNavigationOptions alloc] initEmptyOptions]; initialOptions.bottomTabs.titleDisplayMode = [[Text alloc] initWithValue:@"alwaysHide"]; - [[self.boundViewController expect] setTabItemImagesCentered]; + [[self.boundViewController expect] centerTabItems]; [self.uut applyOptionsOnInit:initialOptions]; [self.boundViewController verify]; } diff --git a/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m b/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m index b9f36f71c41..35fdef02af9 100644 --- a/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m +++ b/lib/ios/ReactNativeNavigationTests/UITabBarController+RNNOptionsTest.m @@ -41,9 +41,9 @@ - (void)test_tabBarHideShadow_false { XCTAssertFalse(self.uut.tabBar.clipsToBounds); } -- (void)test_setTabItemImagesCentered { +- (void)test_centerTabItems { [[(id)self.uut.tabBar expect] centerTabItems]; - [self.uut setTabItemImagesCentered]; + [self.uut centerTabItems]; [(id)self.uut.tabBar verify]; } diff --git a/lib/ios/UITabBarController+RNNOptions.h b/lib/ios/UITabBarController+RNNOptions.h index 476fbb3f8f2..f1d09c94fc5 100644 --- a/lib/ios/UITabBarController+RNNOptions.h +++ b/lib/ios/UITabBarController+RNNOptions.h @@ -18,6 +18,6 @@ - (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated; -- (void)setTabItemImagesCentered; +- (void)centerTabItems; @end diff --git a/lib/ios/UITabBarController+RNNOptions.m b/lib/ios/UITabBarController+RNNOptions.m index 26e6f930701..5af6788d141 100644 --- a/lib/ios/UITabBarController+RNNOptions.m +++ b/lib/ios/UITabBarController+RNNOptions.m @@ -75,7 +75,7 @@ - (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated { } } -- (void)setTabItemImagesCentered { +- (void)centerTabItems { [self.tabBar centerTabItems]; }