Skip to content

Commit fe024ea

Browse files
committed
Restore bottomTabs visibility when needed (#6298)
Until now, `tabBar.frame` got restored each time child appeared which resulted in wrong bottomTabs visibility. In this PR we changed it so the `tabBar.frame` will get restored only after the tabBar frame has changed through `mergeOptions`. Closes #6282
1 parent 5b7356d commit fe024ea

File tree

9 files changed

+89
-54
lines changed

9 files changed

+89
-54
lines changed

e2e/BottomTabs.test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,16 @@ describe('BottomTabs', () => {
7575
await elementById(TestIDs.POP_BTN).tap();
7676
await expect(elementById(TestIDs.BOTTOM_TABS)).toBeVisible();
7777
});
78+
79+
it('hide Tab Bar on push from second bottomTabs screen - deep stack', async () => {
80+
await elementById(TestIDs.SWITCH_TAB_BY_INDEX_BTN).tap();
81+
await elementById(TestIDs.HIDE_TABS_PUSH_BTN).tap();
82+
await expect(elementById(TestIDs.BOTTOM_TABS)).toBeNotVisible();
83+
await elementById(TestIDs.PUSH_BTN).tap();
84+
await expect(elementById(TestIDs.BOTTOM_TABS)).toBeVisible();
85+
await elementById(TestIDs.POP_BTN).tap();
86+
await expect(elementById(TestIDs.BOTTOM_TABS)).toBeNotVisible();
87+
await elementById(TestIDs.POP_BTN).tap();
88+
await expect(elementById(TestIDs.BOTTOM_TABS)).toBeVisible();
89+
});
7890
});

lib/ios/BottomTabsBasePresenter.m

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#import "BottomTabsBasePresenter.h"
2+
#import "RNNBottomTabsController.h"
23

34
@implementation BottomTabsBasePresenter
45

@@ -13,11 +14,11 @@ - (void)applyOptionsOnInit:(RNNNavigationOptions *)options {
1314
}
1415

1516
- (void)applyOptions:(RNNNavigationOptions *)options {
16-
UITabBarController *bottomTabs = self.tabBarController;
17+
RNNBottomTabsController *bottomTabs = self.tabBarController;
1718
RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
1819

1920
[bottomTabs setTabBarTestID:[withDefault.bottomTabs.testID getWithDefaultValue:nil]];
20-
![withDefault.bottomTabs.visible getWithDefaultValue:YES] ?: [bottomTabs setTabBarVisible:[withDefault.bottomTabs.visible getWithDefaultValue:YES] animated:[withDefault.bottomTabs.animate getWithDefaultValue:NO]];
21+
[bottomTabs restoreTabBarVisibility:[withDefault.bottomTabs.visible getWithDefaultValue:YES]];
2122

2223
[bottomTabs.view setBackgroundColor:[withDefault.layout.backgroundColor getWithDefaultValue:nil]];
2324
[self applyBackgroundColor:[withDefault.bottomTabs.backgroundColor getWithDefaultValue:nil] translucent:[withDefault.bottomTabs.translucent getWithDefaultValue:NO]];
@@ -27,7 +28,7 @@ - (void)applyOptions:(RNNNavigationOptions *)options {
2728

2829
- (void)mergeOptions:(RNNNavigationOptions *)options resolvedOptions:(RNNNavigationOptions *)currentOptions {
2930
[super mergeOptions:options resolvedOptions:currentOptions];
30-
UITabBarController *bottomTabs = self.tabBarController;
31+
RNNBottomTabsController *bottomTabs = self.tabBarController;
3132

3233
if (options.bottomTabs.currentTabIndex.hasValue) {
3334
[bottomTabs setCurrentTabIndex:options.bottomTabs.currentTabIndex.get];
@@ -72,8 +73,8 @@ - (void)mergeOptions:(RNNNavigationOptions *)options resolvedOptions:(RNNNavigat
7273
}
7374
}
7475

75-
- (UITabBarController *)tabBarController {
76-
return (UITabBarController *)self.boundViewController;
76+
- (RNNBottomTabsController *)tabBarController {
77+
return (RNNBottomTabsController *)self.boundViewController;
7778
}
7879

7980
- (UITabBar *)tabBar {

lib/ios/RNNBasePresenter.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ - (BOOL)getStatusBarVisibility {
120120
}
121121

122122
- (BOOL)hidesBottomBarWhenPushed {
123-
RNNNavigationOptions *withDefault = (RNNNavigationOptions *)[[self.boundViewController.topMostViewController.resolveOptions withDefault:self.defaultOptions] mergeOptions:self.boundViewController.options];
123+
RNNNavigationOptions *withDefault = (RNNNavigationOptions *)[self.boundViewController.topMostViewController.resolveOptions withDefault:self.defaultOptions];
124124
return ![withDefault.bottomTabs.visible getWithDefaultValue:YES];
125125
}
126126

lib/ios/RNNBottomTabsController.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121

2222
- (void)setSelectedIndexByComponentID:(NSString *)componentID;
2323

24+
- (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated;
25+
26+
- (void)restoreTabBarVisibility:(BOOL)visible;
27+
2428
@property (nonatomic, strong) NSArray* pendingChildViewControllers;
2529

2630
@end

lib/ios/RNNBottomTabsController.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ @interface RNNBottomTabsController ()
1010
@implementation RNNBottomTabsController {
1111
NSUInteger _currentTabIndex;
1212
BottomTabsBaseAttacher* _bottomTabsAttacher;
13+
BOOL _tabBarNeedsRestore;
1314

1415
}
1516

@@ -110,6 +111,18 @@ - (void)loadChildren:(NSArray *)children {
110111
}
111112
}
112113

114+
- (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated {
115+
_tabBarNeedsRestore = YES;
116+
visible ? [self showTabBar:animated] : [self hideTabBar:animated];
117+
}
118+
119+
- (void)restoreTabBarVisibility:(BOOL)visible {
120+
if (_tabBarNeedsRestore) {
121+
[self setTabBarVisible:visible animated:NO];
122+
_tabBarNeedsRestore = NO;
123+
}
124+
}
125+
113126
#pragma mark UITabBarControllerDelegate
114127

115128
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {

lib/ios/UITabBarController+RNNOptions.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414

1515
- (void)setTabBarHideShadow:(BOOL)hideShadow;
1616

17-
- (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated;
18-
1917
- (void)centerTabItems;
2018

19+
- (void)showTabBar:(BOOL)animated;
20+
21+
- (void)hideTabBar:(BOOL)animated;
22+
2123
@end

lib/ios/UITabBarController+RNNOptions.m

Lines changed: 45 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -28,51 +28,54 @@ - (void)setTabBarHideShadow:(BOOL)hideShadow {
2828
self.tabBar.clipsToBounds = hideShadow;
2929
}
3030

31-
- (void)setTabBarVisible:(BOOL)visible animated:(BOOL)animated {
32-
const CGRect tabBarFrame = self.tabBar.frame;
33-
const CGRect tabBarVisibleFrame = CGRectMake(tabBarFrame.origin.x,
34-
self.view.frame.size.height - tabBarFrame.size.height,
35-
tabBarFrame.size.width,
36-
tabBarFrame.size.height);
37-
const CGRect tabBarHiddenFrame = CGRectMake(tabBarFrame.origin.x,
38-
self.view.frame.size.height,
39-
tabBarFrame.size.width,
40-
tabBarFrame.size.height);
41-
if (!animated) {
42-
self.tabBar.hidden = !visible;
43-
self.tabBar.frame = visible ? tabBarVisibleFrame : tabBarHiddenFrame;
44-
return;
45-
}
46-
static const CGFloat animationDuration = 0.15;
31+
- (void)centerTabItems {
32+
[self.tabBar centerTabItems];
33+
}
34+
4735

48-
if (visible) {
49-
self.tabBar.hidden = NO;
50-
[UIView animateWithDuration: animationDuration
51-
delay: 0
52-
options: UIViewAnimationOptionCurveEaseOut
53-
animations:^()
54-
{
55-
self.tabBar.frame = tabBarVisibleFrame;
56-
}
57-
completion:^(BOOL finished)
58-
{}];
59-
} else {
60-
[UIView animateWithDuration: animationDuration
61-
delay: 0
62-
options: UIViewAnimationOptionCurveEaseIn
63-
animations:^()
64-
{
65-
self.tabBar.frame = tabBarHiddenFrame;
66-
}
67-
completion:^(BOOL finished)
68-
{
69-
self.tabBar.hidden = YES;
70-
}];
71-
}
36+
- (void)showTabBar:(BOOL)animated {
37+
static const CGFloat animationDuration = 0.15;
38+
const CGRect tabBarVisibleFrame = CGRectMake(self.tabBar.frame.origin.x,
39+
self.view.frame.size.height - self.tabBar.frame.size.height,
40+
self.tabBar.frame.size.width,
41+
self.tabBar.frame.size.height);
42+
self.tabBar.hidden = NO;
43+
if (!animated) {
44+
self.tabBar.frame = tabBarVisibleFrame;
45+
} else {
46+
[UIView animateWithDuration: animationDuration
47+
delay: 0
48+
options: UIViewAnimationOptionCurveEaseOut
49+
animations:^()
50+
{
51+
self.tabBar.frame = tabBarVisibleFrame;
52+
} completion:^(BOOL finished)
53+
{}];
54+
}
7255
}
7356

74-
- (void)centerTabItems {
75-
[self.tabBar centerTabItems];
57+
- (void)hideTabBar:(BOOL)animated {
58+
static const CGFloat animationDuration = 0.15;
59+
const CGRect tabBarHiddenFrame = CGRectMake(self.tabBar.frame.origin.x,
60+
self.view.frame.size.height,
61+
self.tabBar.frame.size.width,
62+
self.tabBar.frame.size.height);
63+
64+
if (!animated) {
65+
self.tabBar.frame = tabBarHiddenFrame;
66+
self.tabBar.hidden = YES;
67+
} else {
68+
[UIView animateWithDuration: animationDuration
69+
delay: 0
70+
options: UIViewAnimationOptionCurveEaseOut
71+
animations:^()
72+
{
73+
self.tabBar.frame = tabBarHiddenFrame;
74+
} completion:^(BOOL finished)
75+
{
76+
self.tabBar.hidden = YES;
77+
}];
78+
}
7679
}
7780

7881
- (void)forEachTab:(void (^)(UIView *, UIViewController * tabViewController, int tabIndex))performOnTab {

playground/ios/NavigationIOS12Tests/RNNBottomTabsPresenterTest.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ - (void)testApplyOptions_shouldSetDefaultEmptyOptions {
2828
[[(id)self.uut expect] applyBackgroundColor:nil translucent:NO];
2929
[[self.boundViewController expect] setTabBarHideShadow:NO];
3030
[[self.boundViewController expect] setTabBarStyle:UIBarStyleDefault];
31-
[[self.boundViewController expect] setTabBarVisible:YES animated:NO];
31+
[[self.boundViewController expect] restoreTabBarVisibility:YES];
3232
[self.uut applyOptions:emptyOptions];
3333
[self.boundViewController verify];
3434
}
@@ -55,7 +55,7 @@ - (void)testApplyOptions_shouldRestoreHiddenTabBar {
5555
RNNNavigationOptions *initialOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
5656
initialOptions.bottomTabs.visible = [[Bool alloc] initWithValue:@(1)];
5757

58-
[[self.boundViewController expect] setTabBarVisible:YES animated:NO];
58+
[[self.boundViewController expect] restoreTabBarVisibility:YES];
5959

6060
[self.uut applyOptions:initialOptions];
6161
[self.boundViewController verify];

playground/ios/NavigationTests/RNNBottomTabsAppearancePresenterTest.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ - (void)testApplyOptions_shouldSetDefaultEmptyOptions {
3636
[[self.boundViewController expect] setTabBarTestID:nil];
3737
[[(id)self.uut expect] applyBackgroundColor:nil translucent:NO];
3838
[[self.boundViewController expect] setTabBarHideShadow:NO];
39-
[[self.boundViewController expect] setTabBarVisible:YES animated:NO];
39+
[[self.boundViewController expect] restoreTabBarVisibility:YES];
4040
[[self.boundViewController expect] setTabBarStyle:UIBarStyleDefault];
4141
[self.uut applyOptions:emptyOptions];
4242
[self.boundViewController verify];
@@ -64,7 +64,7 @@ - (void)testApplyOptions_shouldRestoreHiddenTabBar {
6464
RNNNavigationOptions *initialOptions = [[RNNNavigationOptions alloc] initEmptyOptions];
6565
initialOptions.bottomTabs.visible = [[Bool alloc] initWithValue:@(1)];
6666

67-
[[self.boundViewController expect] setTabBarVisible:YES animated:NO];
67+
[[self.boundViewController expect] restoreTabBarVisibility:YES];
6868

6969
[self.uut applyOptions:initialOptions];
7070
[self.boundViewController verify];

0 commit comments

Comments
 (0)