Closed maplebaby closed 9 years ago
+1
+1.
I hide the tabbar with toggle the hidden property of the tabbar in tabBarController,but when i swipe back,the animation effect in tabbar disappears.Looking forward to a better hack.
You could use Navigator on your index and set the initial route to your TabBars. Now, any new screen that is pushed will overlap your TabBar screen.
@maplebaby Were you ever able to figure out a solution?
@christopherdro: I'm guessing your proposed solution would mean that ANY scenes pushed onto the stack from that initial route would overlap and cover the tab bar?
@achang28 Yes, in that case any scene will overlap your tab bars.
+1 @christopherdro Can you give a example code? Thanks.
So the final solution is a new design form like above? Any other solution or can someone make it detail about how to achieve the above solution?
+10086
You also might want to consider using a JS-based tabbed-navigator, eg: https://github.com/exponentjs/react-native-tab-navigator
Here's the sample code. https://rnplay.org/apps/-P8G_w
@ide @brentvatne Issue can be closed. Example and alternate method provided.
Neat, thanks @christopherdro!
Is there an alternative way that doesn't always overlap your tab bar on a new scene?
What is happening to me is that my original login screen doesn't have a tab bar. When a user logs in / signs up, all scenes have a tab bar. When the user logs out, I call this.props.navigator.push to go back to the initial route (which would be the login page) - but it has the tab bar appear on the page, which is not what I want.
I add hidesBottomBarWhenPushed in react code but tabbar is not hidden.
so I modify the RCTNavItem code,add a property control tabbar visible, like @property (nonatomic, assign) BOOL showTabBar;
in RCTNavItemManager.m RCT_EXPORT_VIEW_PROPERTY(showTabBar, BOOL)
and modify the method
final add a propType in NavigatorIOS.ios.js
@yangaqi Thanks!!!
I'm not using the NavigatorIOS component; I'm using the Navigator component.
Will this solution to the issue need to be changed?
You could use nested navigators, where the top-level navigator contains two scenes: logged-out and logged-in. The logged-in scene would have a tab bar with a navigator for each tab.
@ide thanks. I'll give this a go as well.
@christopherdro in the example you provided, if the navigator has a navigation bar, it would be exactly the same navigation bar when switching between tabs. It means I need to somehow change nav bar myself when switching between tabs -- I don't even know it's possible to do so.
Any ideas on handling the nav bar? As I understood, hide/show Nav bar is also not supported...
@yangaqi Thank you! It works!
@yangaqi can you please tell me what is the filename to modify that method ?
Also, anyone has a solution working ?
UPDATE: I have it working now for my situation (I wanted 3 tabs to show the tab bar and one of the tabs to hide the tab bar)
@christopherdro The proposed solution above may work in some situations, but is not ideal for what I want to do. I hope someone figures out a way to create a PR for this.
@jainmitesh09 here are the files and edits in the Objective-C code as far as i can make out from @yangaqi 's example:
In Xcode's lefthand sidebar, choose the 'Project Manger' (folder icon) to see the file structure.
The particular folder you are looking for is found at: [YourAppName] > Libraries > React.xcodeproj > React > Views
RCTNavItem.h
#import "RCTComponent.h"
@interface RCTNavItem : UIView
//add this line:
@property (nonatomic, assign) BOOL showTabBar;
RCTNavItemManager.m
@implementation RCTNavItemManager
RCT_EXPORT_MODULE()
- (UIView *)view
{
return [RCTNavItem new];
}
// add this line:
RCT_EXPORT_VIEW_PROPERTY(showTabBar, BOOL)
RCTNavigator.m
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(__unused UIViewController *)viewController
animated:(__unused BOOL)animated
{
// Add these two lines:
RCTWrapperViewController *thisController = (RCTWrapperViewController *)viewController;
navigationController.tabBarController.tabBar.hidden = !thisController.navItem.showTabBar;
I did not need to add propTypes to NavigatorIOS.ios.js or TabBarIOS.ios.js
In order for this all to work, each tab seemingly needs to have its own NavigatorIOS component. When I had the tab simply present a screen the - (void)navigationController:(UINavigationController *)navigationController...
method does not get called. This was not an issue for me, because hiding the navBar is easily done with navigationBarHidden: true
.
In my case I had a TabNav
> HomeNav
> HomeScreen
Passing showTabBar prop in HomeNav
:
render() {
return (
<NavigatorIOS
style={styles.container}
client={this.props.client}
initialRoute={{
title: 'Home',
component: HomeScreen,
navigationBarHidden: true,
showTabBar: false,
passProps: { ...},
}}/>
);
}
}
I hope this helps someone!
@mcampsall Thank you ! Got another workaround; used Navigator instead NavigatorIOS. But thanks for the solution. Appreciate it. I'll try it out with NavigatorIOS.
@jainmitesh09 How did you got this working with Navbar? Thanks!
@horatiua, the solution i proposed above includes a nav bar (the NavigatorIOS component). Set up a TabBarIOS like normal and just return a NavigatorIOS component in each tab.
Something like this (not tested):
render() {
return (
<TabBarIOS tintColor={SPColors.blue}>
<TabBarIOS.Item
selected={this.state.selectedTab === 'home'}
title='Home'
icon={require ('./Icons/IconImages/HomeTabIcon.png')}
onPress={() => {
this.setState({
selectedTab: 'home'
});
}}>
<NavigatorIOS
style={styles.container}
ref="nav"
initialRoute={{
title: 'Home',
component: HomeNavigationController,
navigationBarHidden: true,
showTabBar: false,
passProps: {
//pass props here
},
}}/>
</TabBarIOS.Item>
<TabBarIOS.Item
selected={this.state.selectedTab === 'secondTab'}
title='Second Tab'
icon={require ('./Icons/IconImagesSecondTabIcon.png')}
onPress={() => this._tabPressed('secondTab')}>
<NavigatorIOS
style={styles.container}
ref="nav"
initialRoute={{
title: 'SecondTab',
component: SecondTabComponent,
navigationBarHidden: false,
showTabBar: true,
passProps: {
//pass props here
},
}}/>
</TabBarIOS.Item>
</TabBarIOS.Item>
<TabBarIOS.Item
selected={this.state.selectedTab === 'thirdTab'}
title='Third Tab'
icon={require ('./Icons/IconImagesThirdTabIcon.png')}
onPress={() => this._tabPressed('thirdTab')}>
<NavigatorIOS
style={styles.container}
ref="nav"
initialRoute={{
title: 'ThirdTab',
component: ThirdTabComponent,
navigationBarHidden: false,
showTabBar: true,
passProps: {
//pass props here
},
}}/>
</TabBarIOS.Item>
</TabBarIOS>
);
}
@mcampsall Thanks for your suggestion. The issue is that right now I've already implemented a Navigator in every TabBarIOS.Item, as it best fits my app's needs. I nested this TabBarIOS in another Navigator in order to make TabBarIOS disappear. It's an ugly solution (as I had to create some kind of router in order to work fine with Redux), but it works... A "navigationBarHidden" property for TabBarIOS would be very useful, though.
RCTWrapperViewController.m
- (BOOL)hidesBottomBarWhenPushed
{
return self.navigationController.viewControllers.count != 1;
}
RCTTabBar.m
- (void)reactBridgeDidFinishTransaction
{
...
if (_tabsChanged) {
NSMutableArray<UIViewController *> *viewControllers = [NSMutableArray array];
for (RCTTabBarItem *tab in [self reactSubviews]) {
UIViewController *controller = tab.reactViewController;
if (!controller) {
NSArray *tabSubViews = [[[tab reactSubviews] firstObject] reactSubviews];
RCTNavigator *navigator = [tabSubViews firstObject];
if (!tabSubViews.count) {
tab.onPress(nil);
return;
}
else if ([navigator isKindOfClass:[RCTNavigator class]]) {
controller = navigator.reactViewController;
}
else {
controller = [[RCTWrapperViewController alloc] initWithContentView:tab];
}
}
[viewControllers addObject:controller];
}
_tabController.viewControllers = viewControllers;
_tabsChanged = NO;
RCTTabBarItem *tab = (RCTTabBarItem *)[[self reactSubviews] firstObject];
tab.onPress(nil);
}
...
}
How To Hide Tab Bar in Navigation Interface