Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ios/BottomTabsBasePresenter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ - (void)applyOptionsOnInit:(RNNNavigationOptions *)options {
[super applyOptionsOnInit:options];
UITabBarController *bottomTabs = self.tabBarController;
RNNNavigationOptions *withDefault = [options withDefault:[self defaultOptions]];
if (@available(iOS 18.0, *)) {
[bottomTabs
setTabBarHidden:![withDefault.bottomTabs.visible withDefault:YES]
animated:NO];
}
[bottomTabs setCurrentTabIndex:[withDefault.bottomTabs.currentTabIndex withDefault:0]];
if (withDefault.bottomTabs.currentTabId.hasValue) {
[bottomTabs setCurrentTabID:withDefault.bottomTabs.currentTabId.get];
Expand Down
2 changes: 1 addition & 1 deletion ios/RNNBottomTabsController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ - (void)layoutCustomRow {
tabBarInView.size.width, desiredHeight);

_customRow.frame = rowFrame;
_customRow.hidden = self.tabBar.hidden;
_customRow.hidden = [self rnn_isTabBarHidden];
[_customRow setSelectedIndex:_currentTabIndex];
}

Expand Down
3 changes: 2 additions & 1 deletion ios/RNNComponentViewController.mm
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#import "RNNComponentViewController.h"
#import "AnimationObserver.h"
#import "UITabBarController+RNNOptions.h"

@implementation RNNComponentViewController {
NSArray *_reactViewConstraints;
Expand Down Expand Up @@ -126,7 +127,7 @@ - (void)updateReactViewFrame {
}

- (BOOL)shouldDrawBehindBottomTabs {
return !self.tabBarController.tabBar || self.tabBarController.tabBar.isHidden ||
return !self.tabBarController.tabBar || [self.tabBarController rnn_isTabBarHidden] ||
_drawBehindBottomTabs;
}

Expand Down
2 changes: 2 additions & 0 deletions ios/UITabBarController+RNNOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

- (void)hideTabBar:(BOOL)animated;

- (BOOL)rnn_isTabBarHidden;

- (void)syncTabBarItemTestIDs;

@end
18 changes: 18 additions & 0 deletions ios/UITabBarController+RNNOptions.mm
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ - (void)centerTabItems {
}

- (void)showTabBar:(BOOL)animated {
if (@available(iOS 18.0, *)) {
[self setTabBarHidden:NO animated:animated];
return;
}

static const CGFloat animationDuration = 0.15;
const CGRect tabBarVisibleFrame = CGRectMake(
self.tabBar.frame.origin.x, self.view.frame.size.height - self.tabBar.frame.size.height,
Expand All @@ -161,6 +166,11 @@ - (void)showTabBar:(BOOL)animated {
}

- (void)hideTabBar:(BOOL)animated {
if (@available(iOS 18.0, *)) {
[self setTabBarHidden:YES animated:animated];
return;
}

static const CGFloat animationDuration = 0.15;
const CGRect tabBarHiddenFrame =
CGRectMake(self.tabBar.frame.origin.x, self.view.frame.size.height,
Expand All @@ -182,6 +192,14 @@ - (void)hideTabBar:(BOOL)animated {
}
}

- (BOOL)rnn_isTabBarHidden {
if (@available(iOS 18.0, *)) {
return self.tabBarHidden;
}

return self.tabBar.hidden;
}
Comment on lines +195 to +201

- (void)forEachTab:(void (^)(UIView *, UIViewController *tabViewController,
int tabIndex))performOnTab {
int tabIndex = 0;
Expand Down
27 changes: 27 additions & 0 deletions playground/ios/NavigationTests/BottomTabsControllerTest.mm
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,33 @@ - (void)testGetCurrentChild_shouldReturnSelectedViewController {
[(RNNBottomTabsController *)self.uut selectedViewController]);
}

- (void)testSetTabBarVisible_shouldUseActiveTabBarVisibilityOnIOS18 {
if (@available(iOS 18.0, *)) {
[self.originalUut setTabBarVisible:NO];
XCTAssertTrue(self.originalUut.tabBarHidden);

[self.originalUut setTabBarVisible:YES];
XCTAssertFalse(self.originalUut.tabBarHidden);
}
}

- (void)testSetTabBarVisible_shouldNotOverrideStackChildVisibilityOnIOS18 {
if (@available(iOS 18.0, *)) {
UIViewController *component =
[RNNComponentViewController createWithComponentId:@"componentId"
initialOptions:[RNNNavigationOptions emptyOptions]];
UINavigationController *stack =
[[UINavigationController alloc] initWithRootViewController:component];
RNNBottomTabsController *uut =
[RNNBottomTabsController createWithChildren:@[ stack ]];

[uut setTabBarHidden:NO animated:NO];
[uut setTabBarVisible:NO];

XCTAssertFalse(uut.tabBarHidden);
}
}

- (void)testPreferredStatusBarStyle_shouldInvokeSelectedViewControllerPreferredStatusBarStyle {
[[self.mockTabBarPresenter expect] getStatusBarStyle];
[self.uut preferredStatusBarStyle];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ - (void)testApplyOptionsOnInit_alwaysShow_shouldNotCenterTabImages {
[self.boundViewController verify];
}

- (void)testApplyOptionsOnInit_shouldApplyInitialVisibilityOnIOS18 {
if (@available(iOS 18.0, *)) {
RNNNavigationOptions *initialOptions = [RNNNavigationOptions emptyOptions];
initialOptions.bottomTabs.visible = [[Bool alloc] initWithValue:@(0)];
[[self.boundViewController expect] setTabBarHidden:YES animated:NO];

[self.uut applyOptionsOnInit:initialOptions];

[self.boundViewController verify];
}
}

- (void)testApplyOptions_shouldApplyOptionsOnInit_alwaysHide_shouldCenterTabImages {
RNNNavigationOptions *initialOptions = [RNNNavigationOptions emptyOptions];
initialOptions.bottomTabs.titleDisplayMode = [[Text alloc] initWithValue:@"alwaysHide"];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,31 @@ - (void)test_tabBarHideShadow_false {
XCTAssertFalse(self.uut.tabBar.clipsToBounds);
}

- (void)test_hideTabBar {
if (@available(iOS 18.0, *)) {
[self.uut hideTabBar:NO];
XCTAssertTrue(self.uut.tabBarHidden);
XCTAssertTrue([self.uut rnn_isTabBarHidden]);
}
}

- (void)test_showTabBar {
if (@available(iOS 18.0, *)) {
self.uut.tabBarHidden = YES;
[self.uut showTabBar:NO];
XCTAssertFalse(self.uut.tabBarHidden);
XCTAssertFalse([self.uut rnn_isTabBarHidden]);
}
}

- (void)test_rnnIsTabBarHidden_shouldUseAvailableVisibilityState {
if (@available(iOS 18.0, *)) {
self.uut.tabBarHidden = YES;
} else {
self.uut.tabBar.hidden = YES;
}

XCTAssertTrue([self.uut rnn_isTabBarHidden]);
}

@end
19 changes: 19 additions & 0 deletions playground/src/screens/LayoutsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const {
WELCOME_SCREEN_HEADER,
STACK_BTN,
BOTTOM_TABS_BTN,
SINGLE_BOTTOM_TAB_MODAL_BTN,
BOTTOM_TABS,
SIDE_MENU_BTN,
KEYBOARD_SCREEN_BTN,
Expand Down Expand Up @@ -78,6 +79,11 @@ export default class LayoutsScreen extends NavigationComponent<NavigationProps,
<Root componentId={this.props.componentId}>
<Button label="Stack" testID={STACK_BTN} onPress={this.stack} />
<Button label="BottomTabs" testID={BOTTOM_TABS_BTN} onPress={this.bottomTabs} />
<Button
label="Single BottomTab Modal"
testID={SINGLE_BOTTOM_TAB_MODAL_BTN}
onPress={this.singleBottomTabModal}
/>
<Button label="BottomTabs Styling" onPress={this.bottomTabsStyling} />
<Button
label="BottomTabs with Role"
Expand Down Expand Up @@ -122,6 +128,19 @@ export default class LayoutsScreen extends NavigationComponent<NavigationProps,
});
};

singleBottomTabModal = () => {
Navigation.showModal({
bottomTabs: {
children: [stack(Screens.FirstBottomTabsScreen)],
options: {
bottomTabs: {
visible: false,
},
},
},
});
};

bottomTabsStyling = () => {
Navigation.showModal({
bottomTabs: {
Expand Down
1 change: 1 addition & 0 deletions playground/src/testIDs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const testIDs = {
MODAL_DISMISSED_LISTENER_RESULT: 'MODAL_DISMISSED_LISTENER_RESULT',
DISMISS_MODAL_PROMISE_RESULT: 'DISMISS_MODAL_PROMISE_RESULT',
BOTTOM_TABS_BTN: 'BOTTOM_TABS_BUTTON',
SINGLE_BOTTOM_TAB_MODAL_BTN: 'SINGLE_BOTTOM_TAB_MODAL_BUTTON',
EXTERNAL_COMP_BTN: 'EXTERNAL_COMPONENT_BUTTON',
LAYOUTS_TAB: 'LAYOUTS_TAB',
NAVIGATION_TAB: 'NAVIGATION_TAB',
Expand Down