Closed zhaoyi0113 closed 6 years ago
Have you tried to use setParams?
https://reactnavigation.org/docs/navigators/navigation-prop#setParams-Make-changes-to-route-params
I tried this code this.props.navigation.setParams({tabBar:{visible:false}})
but it doesn't make the tab bar invisible? Did I pass a wrong parameter?
I think setParams
only works for setting route parameters. But the visible:false
is not a route parameter. Instead it is a configuration set under navigationOptions
. Is there a way to update it dynamically?
mhh yeah maybe u r right. the tabbar node can be an object or and function maybe this will help you ?
The acc function parameter is the navigationOptions of the current open screen for example an stackNavigator subpage.
export const CustomTabNavigator = TabNavigator({
...
Camera: {
screen: CameraTab,
navigationOptions: {
tabBar: (state,acc) => {
return {
visible: (acc && acc.visible !== 'undefined') ? acc.visible : true,
label: 'Camera',
icon: ({focused}) => createTabbarIcon('camera', focused)
}
},
}
},
...
});
Thanks for your response. I understand the general idea. But I don't know how to update the acc
parameter in my component? Is the acc
a state of my component or something else?
i think the acc is this:
static navigationOptions = {
tabBar: {
label: '',
icon: (obj) => {
const image = obj.focused ? require('1.png') : require('2.png');
return <Image style={{resizeMode:'contain', width:40, height: 40}}
source={image}
/>
}
},
};
I see. When I update the acc value, the tab bar didn't get rendered. How can I make it re-render when the property value got changed?
I have the same problem... Is there any example working?
My solution, to animate the tab bar hiding and showing based on navigatino params.
in your TabNavigator declaration:
const MyTabNav = TabNavigator(
{
Home: { Screen: HomeScreen },
Profile: { Screen: ProfileScreen },
},
{
tabBarComponent: TabBar,
}
);
The Tab Bar itself:
import React, { Component } from 'react';
import { Animated } from 'react-native';
import { TabBarBottom } from 'react-navigation';
const TAB_BAR_OFFSET = -60;
export default class TabBar extends Component {
constructor(props) {
super(props);
this.state = {
offset: new Animated.Value(0),
};
}
componentWillReceiveProps(props) {
const oldState = this.props.navigation.state;
const oldRoute = oldState.routes[oldState.index];
const oldParams = oldRoute.params;
const wasVisible = !oldParams || oldParams.visible;
const newState = props.navigation.state;
const newRoute = newState.routes[newState.index];
const newParams = newRoute.params;
const isVisible = !newParams || newParams.visible;
if (wasVisible && !isVisible) {
Animated.timing(this.state.offset, { toValue: TAB_BAR_OFFSET, duration: 200 }).start();
} else if (isVisible && !wasVisible) {
Animated.timing(this.state.offset, { toValue: 0, duration: 200 }).start();
}
}
render() {
return (
<TabBarBottom {...this.props} style={[styles.container, { bottom: this.state.offset }]}/>
);
}
}
const styles = {
container: {
overflow: 'hidden',
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'white',
elevation: 8,
},
};
To use it, just call this.props.navigation.setParams({ visible: true/false });
in your HomeScreen or ProfileScreen.
You can of course animate however you want - I choose to have it slide off the screen.
@richardfickling thanks for sharing! I had a problem with animating the
render() {
return (
<Animated.View style={[styles.container, { bottom: this.state.offset }]}>
<TabBarBottom {...this.props} />
</Animated.View>
);
}
it's an animated view on master as of 3 days ago :) https://github.com/react-community/react-navigation/commit/d4ce9b08abf7aa725aca8305e841e1adf48d8a44
I had your code exactly until that change was merged.
Thanks @richardfickling @markjongkind this was a great guide. I was having trouble with setParams as I had a stack navigator nested inside a tab navigator, so what i ended up doing was making the TabBar component a connected (redux) component and going off of the props:
componentWillReceiveProps(nextProps) {
const wasVisible = this.props.tabBarOpen;
const isVisible = nextProps.tabBarOpen;
if (wasVisible && !isVisible) {
Animated.timing(this.state.offset, { toValue: TAB_BAR_OFFSET, duration: 200 }).start();
} else if (isVisible && !wasVisible) {
Animated.timing(this.state.offset, { toValue: 0, duration: 150 }).start();
}
then:
const mapStateToProps = (state) => ({
tabBarOpen: state.admin.tabBarOpen,
});
export default connect(mapStateToProps)(TabBar);
Thanks for the guide!
@satya164 a recent update change to react-native-tab-view (https://github.com/react-native-community/react-native-tab-view/commit/c80fdff7bdb59b281c324bb6fb0dd1f213c1aae6) broke my workaround using an absolutely positioned tab view. Any chance we can add a way to send a style prop to the container view (or find a cleaner solution to the zIndex bug)? I'll send a PR for the style prop if that works for you
Hmm. I might have an idea on how to fix that. Let's see.
@satya164 what idea ?
Hi All
I have just used simple react-navigation and I have stacked navigation
i.e
StackNavigator TabNavigator -- (stack navigor - view1,view2 etc..)
Now how I can show/hide tab bar in view1, after it is rendered?
Note: I have not used react-native-tab-view or no other packages.
Please guide me in this.
Please also let me know if there is any alternative for this....
Hi @richardfickling
your solution worked. Thanks you saved my life...
oops this.props.navigation.setParams({ visible: true/false }); is not working when I call this from inner component for example...
When we have something like
Stacknavigator --Tabnavigator ----Stacknavigator ------Screen1(somehow works here)-->navigatates to screen-2 (not working here)
Whether I am missing anything here?
@richardfickling and @markjongkind thanks for your both suggestion and solution. I got one problem is my indicatorStyle
not apply to the TabBar component, any idea ?
Any updates to this?
I found a Working Solution around this:
in the screen you want to hide tab bar update the navigation option. the key is enabling animationEnabled
to true and hide the tabBar using tabBarVisible
property.
static navigationOptions = ({navigation}) => ({ tabBarVisible: (navigation.state.params && navigation.state.params.hideTabBar) === true, animationEnabled: true )}
make tabBar visible in componentWillMount
.
componentWillMount() { const setParamsAction = NavigationActions.setParams({ params: {hideTabBar: true} }); this.props.navigation.dispatch(setParamsAction); }
and in componentWillUnmount
hide the tabBar again
componentWillUnmount() { const setParamsAction = NavigationActions.setParams({ params: {hideTabBar: false} }); this.props.navigation.dispatch(setParamsAction); }
please re-post to https://react-navigation.canny.io/feature-requests if this is important for you. re-organizing issues to focus on bug reports here and feature requests on canny. thanks!
same issue when I try show fullscreen modal? Who can help me?
@gamingumar what is animationEnabled
for? For me it also worked by simply setting
class ScreenWhereTabbarIsHidden extends React.Component {
static navigationOptions = {
tabBarVisible: false,
}
}
@schumannd the problem happens when you have a back button. which doesn't work if animationEnabled
is not true
I am using a custom back button like so:
StackNavigator({
...
}, {
navigationOptions: ({ navigation }) => ({
headerLeft: <BackButton navigation={navigation} />,
}),
});
and did not encounter any problems. Can you elaborate why the option would break the back button?
unable to find working solution out of above.
I was able to get a working solution using route keys. My setup is a TabNavigator with a nested StackNavigator so YMMV.
In TabNavigator, use whatever param you want:
screen: NavigationCamera,
navigationOptions: ({ navigation }) => {
const showTabBar = navigation.state && navigation.state.routes && navigation.state.routes[0] && navigation.state.routes[0].params ? navigation.state.routes[0].params.showTabBar : true;
return {
tabBarLabel: 'Live',
path: '/camera',
tabBarIcon: ({ tintColor }) => (
<Ionicons
name={'ios-radio-outline'}
size={28}
style={{ color: tintColor, top: 2 }}
/>
),
tabBarVisible: showTabBar,
};
},
In your component where you want to hide the tab bar, do your boolean check and set showTabBar with the route key:
const setParamsAction = NavigationActions.setParams({
params: { showTabBar: false/true },
key: this.props.navigation.state.key,
});
this.props.navigation.dispatch(setParamsAction);
@adamawang i tried your solution but it did not worked
@adamawang u'r awesome!
@vksgautam1 to work him answer, change this: const setParamsAction = NavigationActions.setParams({ params: { showTabBar: false/true }, key: this.props.navigation.state.key, }); this.props.navigation.dispatch(setParamsAction);
to this: const setParamsAction = this.props.navigation.setParams({ params: { showTabBar: true }, key: this.props.navigation.state.key, }); this.props.navigation.dispatch(setParamsAction);
For anyone still figuring out how to hide navigation elements dynamically.
If you're using redux, and custom headers/tab bars/whatever.
Create a UI ducks module like:
export interface State {
headerHidden: boolean;
topTabBarHidden: boolean;
bottomTabBarHidden: boolean;
}
Then in your custom header just return hull if headerHidden is true:
const NavBar: React.SFC<NavBarProps> = props =>
props.headerHidden ? null : <Header {...props} />;
This is what we're using when we want fullscreen video in nested navigators. Hopefully it helps someone.
// Dynamically hidding - simple
// In stack navigation add default
screen: yourScreen,
navigationOptions: {
tabBarVisible: false
}
// On component add
static navigationOptions = ({ navigation }) => ({
title: 'Wall',
tabBarVisible: navigation.getParam('tabBarVisible') === false ? false : true
});
// trigger
this.props.navigation.setParams({ tabBarVisible: false/true });
@SmiljanicN , This does not work for me in the componentDidUpdate life cycle method. Where could i be wrong?
@SmiljanicN this doesn't work inside a StackNavigator?
With me, this one works well react-navigation: "2.2.0"
// In Component
navigationOptions = (navigation) => {
const visible = (navigation.state && navigation.state.routes[0].params) ?
navigation.state.routes[0].params.showTabBar
: true; // default is show
return {
tabBarVisible: visible,
};
};
Then invoke
this.props.navigation.setParams({ showTabBar: show });
tabBarVisible: !navigation.state || (navigation.state.routes[navigation.state.routes.length - 1] || {}).routeName !== 'whateverroutenameyouwanttohideon'
@forster-thomas
const setParamsAction = this.props.navigation.setParams({ params: { showTabBar: false }, key: this.props.navigation.state.key, });
in console.log it shows boolean true and props shows params undefined.
edit -
so i changed it to
const setParamsAction = this.props.navigation.actions.setParams({ params: { showTabBar: false }, key: this.props.navigation.state.key, });
now i am getting
{"type":"Navigation/SET_PARAMS","key":"id-1530608852402-1","params":{"params":{"showTabBar":false},"key":"id-1530608852402-1"}}
and dispatching it but it is not hiding;
const showTabBar = navigation.state && navigation.state.routes && navigation.state.routes[0] && navigation.state.routes[0].params ? navigation.state.routes[0].params.showTabBar : true;
in console navigation is not showing routes key
@vksgautam1 You should be careful with "navigation.state.routes[0]". The params may not at position 0 of array navigation.state.routes. You can print out value of navigation.state.routes to get exact position. In my case: navigation.state.routes[1].params.params.showTabBar
@toanphan0303 Thanks . i am printing the data but it is not showing routes key
This is a solution that worked for me! Applicable if the Tab Navigator contains Stack Navigators and the screens you want to hide are in the Stack Navigators
in the file of the stack, insert this after you have exported/created the class
export default YourStack
const hiddenTabBars = ['Route1', 'Route2'] //these are the RouteNames of the screens you want to hide the tab bars on
YourStack.navigationOptions = ({ navigation }) => {
let tabBarVisible = true
if (
hiddenTabBars.includes(
navigation.state.routes[navigation.state.index].routeName,
)
) {
tabBarVisible = false
}
return {
tabBarVisible,
}
@markjongkind it works . But the tarbar will blink out,especially when you route back with the gesture . Any good ideas about this.
In my situation the bottom tab bar is hidden by default. This is the code for the component:
import React, { Component } from 'react'
import {View, Text } from 'react-native';
import { createStackNavigator, NavigationActions } from 'react-navigation';
import Feed from '../components/Feed';
import Camera from '../components/Camera'
const Router = createStackNavigator({
Feed : {
screen : Feed
},
Camera : {
screen : Camera
}
});
export default class Home extends Component {
static navigationOptions = ({navigation}) => ({
tabBarVisible: (navigation.state.params && navigation.state.params.hideTabBar) === true,
animationEnabled: true
})
componentWillMount() {
const setParamsAction = NavigationActions.setParams({
params: {hideTabBar: true}
});
this.props.navigation.dispatch(setParamsAction);
}
componentWillUnmount() {
const setParamsAction = NavigationActions.setParams({
params: {hideTabBar: false}
});
this.props.navigation.dispatch(setParamsAction);
}
render() {
return (
<View style = {{flex : 1}}>
<Router/>
</View>
)
}
}
一顿操作猛如虎啊,没有一个能用的啊
The solution worked well. You must check your router hierarchy to keep the param corresponding to the right one. My method is to console.log the navigation in the navigationOptions function to check where is the params object, maybe they are very deep.
@richardfickling Getting this crash on using the code suggested by you.
@SmiljanicN thanks man!
If you have a navigation struction with nested stack in tab:
You can pass tab's navigation through screenProps
as a rootNavigation
field, and use it later in the Home
component to update route params.
here is a solution https://stackoverflow.com/a/62134625/8079868
@richardfickling感谢您的分享!我在为组件设置动画时遇到问题,因为它不是
。以下代码修复了以下问题: render() { return ( <Animated.View style={[styles.container, { bottom: this.state.offset }]}> <TabBarBottom {...this.props} /> </Animated.View> ); }
in v5.0 <Animated.View>
Where to put it?
Below is my code on a tab bar component.
Can I hide the tab bar dynamically? I know I can add
visible: false
undertabBar
property but I want to show/hide based on a component state. How can I achieve this?