I want to show a back button in the header of a screen that is nested in 2 navigators.
I will first show you how I am nesting the screen, followed by what I have tried
Main stack navigator:
<Provider store = {store}>
<StatusBar style="light" />
<NavigationContainer>
<Stack.Navigator initialRouteName="Login">
<Stack.Screen name="Login"
component={Login}
options= {{
headerLeft: null,
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 20,
color: '#FFFFFF'
},
headerStyle: {
backgroundColor: '#121212'
}
}}/>
<Stack.Screen
name="Tabs"
component={Tabs} <-------------- The screen is nested in tabs
options= {{
title: " ",
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 24,
color: '#FFFFFF'
},
headerStyle: {
backgroundColor: '#121212'
},
}}/>
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
}
}
Tab navigator, nested within the stack navigator as "Tabs":
//Bottom Tabs
function Tabs() {
return (
<Tab.Navigator
initialRouteName="Home"
tabBarOptions={{
activeTintColor:"#FFFFFF",
inactiveTintColor:"#696969",
style: {
backgroundColor: '#000000'
},
}}>
<Tab.Screen
name="Create"
component={createFlowStack} <------------ This stack is where the screen header I want to add a back button to lies
options={{
tabBarLabel: ' ',
tabBarIcon: ({ color, size }) => (
<Ionicons name="md-add-circle" size={size} color={color} />
),
}}
/>
</Tab.Navigator>
);
}
I have deleted the other tabs as they are not relevant to the question. This tab, create, is nesting another stack navigator, createFlowStack:
createFlowStack, which is shown when you click on the bottom tab "create"
<CreateStack.Navigator
initialRouteName="Create"
>
<CreateStack.Screen
name="Create"
component={Create} />
<CreateStack.Screen
name="Screenshot"
component={Screenshot}
// options={({ navigation }) => ({
// headerRight: () => (
// <Button
// onPress={() => navigation.goBack()}
// title="Info"
// color="#fff" />
// ),
// })}
/>
As you can see, the options are commented out, but it wouldn't matter any way. I am trying to show a back button in header left of this screen, but nothing I have tried works.
What I have tried:
headerBackTitle: "back"
headerBackTitle: " "
A custom header left button
headerRight: " "
The custom header right button you see commented out
NOTHING works, nothing shows up, its like one of the navigators that createFlowStack is nested in is overriding everything. Please let me know how to fix this issue!
Updating the expo SDK from 39 to 40 fixed the issue!
Related
I have a tab bar that looks like this:
The two side buttons are stack navigators (Learn and Journal) and the middle button needs to navigate the Journal Stack, and depending on what screen in the Journal Stack the user is on, it needs to say and do different things.
const Tab = createBottomTabNavigator();
const TabBarIcon = ({ icon, title, focused }) => {
return (
<View style={styles.iconContainer}>
<FontAwesomeIcon
icon={icon}
color={focused ? Colors.neutral[4] : Colors.neutral[6]}
size={24}
style={styles.icon}
/>
<Text style={[styles.iconText, focused && styles.iconTextFocused]}>
{title}
</Text>
</View>
);
};
const NullScreen = () => null;
const TabNavigator = () => {
return (
<Tab.Navigator
initialRouteName="Journal"
screenOptions={({ route }) => ({
...defaultNavOptions,
headerShown: false,
tabBarStyle: { backgroundColor: Colors.neutral[3] },
tabBarShowLabel: false,
})}
>
<Tab.Screen
name="Learn"
component={LearnStackNavigator}
options={{
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
title={'Learn'}
icon={faUserGraduate}
/>
),
}}
/>
<Tab.Screen
name="Null Screen"
component={NullScreen}
options={{
tabBarButton: ({ focused }) => (
<View
style={{
position: 'relative',
bottom: 25,
width: 80,
height: 80,
borderRadius: '50%',
backgroundColor: 'grey',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
shadowColor: 'black',
shadowOpacity: 0.3,
shadowOffset: { width: 0, height: 2 },
shadowRadius: 3,
}}
>
<TouchableOpacity onPress={() => Alert.alert('hello world')}> // This is the button that I want use for useful things
<View style={[styles.iconContainer, styles.paddingBottom10]}>
<FontAwesomeIcon
icon={faPlus}
color={focused ? Colors.neutral[4] : Colors.neutral[6]}
size={32}
/>
<Text style={styles.iconText}>{'Add Sport'}</Text>
</View>
</TouchableOpacity>
</View>
),
}}
/>
<Tab.Screen
name="Journal"
component={LogbookStackNavigator}
options={{
tabBarIcon: ({ focused }) => (
<TabBarIcon focused={focused} title={'Journal'} icon={faPenAlt} />
),
}}
/>
</Tab.Navigator>
);
};
And here is what the LogbookStackNavigator looks like:
const LogbookStack = createStackNavigator();
const LogbookStackNavigator = () => {
return (
<LogbookStack.Navigator
screenOptions={{
...defaultNavOptions,
headerBackTitleVisible: false,
}}
>
<LogbookStack.Screen
name="Screen1"
component={screen1Component}
options={defaultNavOptions}
/>
<LogbookStack.Screen
name="Screen2"
component={screen2Component}
options={defaultNavOptions}
/>
<LogbookStack.Screen
name="Screen3"
component={screen3Component}
options={entryScreenOptions}
/>
<LogbookStack.Screen
name="Screen4"
component={screen4Component}
options={SaveLogbookScreenOptions}
/>
<LogbookStack.Screen
name="Screen5"
component={screen1Component5}
options={defaultNavOptions}
/>
</LogbookStack.Navigator>
);
};
I know how to use navigation.setOptions, but it only affects the immediate parent navigator, not the grandparent navigator.
Another thing I tried was to make the big circle button on the page itself, but it always rendered underneath the Tab Navigator. If there was a way to make it render above, I think I could just use that. I tried 'position: 'absolute', etc and it always rendered underneath the tab navigator. As it is, I had to basically make a dummy screen in the tab navigator to give me the button on top.
What I need to be able to do, is use big circle button on the Tab Navigator, to navigate to different screens in the LogbookStackNavigator. How do I do that?
Also, I need the title to change from "Add Sport" to "Add " depending on what screen the LogbookStackNavigator is on. How do I do that?
Thanks for your help
Finally figured this out. You have to use react-native-portalize. Just wrap the elements you want to be rendered on top in a
<Portal></Portal>. This will place it above a Bottom Tab navigator.
import { Portal } from 'react-native-portalize';
const FooterButton = () => {
return(
<Portal>
<View>
<Text>I appear above the Tab Navigator!</Text>
</View>
</Portal>
);
export default FooterButton;
Don't forget to wrap the whole app in the the Host:
//In app.js
import { Host } from 'react-native-portalize';
const App = () => {
return (
<Host>
<NavigationContainer>
<AppNavigator />
</NavigationContainer>
</Host>
)
}
export default App;
NOTE: The elements inside the Portal, do not clear when the navigator navigates to another screen. So to get around this, you have to only display the Portal, when the screen is active. Thankfully React Navigation 5+ provides a useIsFocused hook that accomplishes this perfectly.
import { Portal } from 'react-native-portalize';
import { useIsFocused } from '#react-navigation/native';
const FooterButton = () => {
const isFocused = useIsFocused();
// Only display the button when screen is focused. Otherwise, it doesn't go away when you switch screens
return isFocused ? (
<Portal>
<View style={styles.buttonContainer}>
<View style={styles.footer}>{props.children}</View>
</View>
</Portal>
) : null;
};
export default FooterButton;
If you want a modal-style popup, you can wrap react-native-modalize and wrap it with react-native-modalize
Thanks to livin52 on Reddit for the solution
How do I make a back button in the stack navigator for web view? Please Help! I keep on trying, but I just get errors. If you can provide me with a code with a back arrow icon. I deleted it, but I actually have five different pages. All of them have a bottom navigation bar, a stack navigation bar, and is using webview. How do I make a back button in the stack navigator? Please Help! Thank you!
// pages
function HomeScreen({ navigation }) {
return (
<WebView
source={{
uri: 'https://www.stoodnt.com/'
}}
style={{ marginTop: -120 }}
/>
);
}
// Stack Navigation
const HomeStack = createStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
</HomeStack.Navigator>
);
}
// Bottom Navigation
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? 'ios-home'
: 'ios-home';
}
return <Ionicons name={iconName} size={40} color={'orange'} />;
},
})}
tabBarOptions={{
activeTintColor: '#000000',
inactiveTintColor: '#616161',
labelStyle: {
fontSize: 11,
},
style: {
backgroundColor: '#F7F7F7',
},
}}
>
<Tab.Screen name="Home" component={HomeStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
How do I make a back button in the stack navigator for web view? Please Help! I keep on trying, but I just get errors. If you can provide me with a code with a back arrow icon. I deleted it, but I actually have five different pages. All of them have a bottom navigation bar, a stack navigation bar, and is using webview. How do a back button in the stack navigator? Thank you!
// pages
function HomeScreen({ navigation }) {
return (
<WebView
source={{
uri: 'https://www.stoodnt.com/'
}}
style={{ marginTop: -120 }}
/>
);
}
// Stack Navigation
const HomeStack = createStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
</HomeStack.Navigator>
);
}
// Bottom Navigation
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? 'ios-home'
: 'ios-home';
}
return <Ionicons name={iconName} size={40} color={'orange'} />;
},
})}
tabBarOptions={{
activeTintColor: '#000000',
inactiveTintColor: '#616161',
labelStyle: {
fontSize: 11,
},
style: {
backgroundColor: '#F7F7F7',
},
}}
>
<Tab.Screen name="Home" component={HomeStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
You can try this
import { HeaderBackButton } from '#react-navigation/stack';
<HomeStack.Screen
name="Home"
component={HomeScreen}
options={{
headerLeft: ({navigation}) => (
<HeaderBackButton onPress={()=>{navigation.navigate('PAGE NAME')}}/>
),
}}
/>
I'm facing a problem with my Bottom Tab Navigator. I get a white space between my tabs and the end of the screen of my iPhone 11 Simulator. On a iPhone 8 Simulator I don't have these white space. There is also a small white space above the Tabs. How can I remove this space? I'm not able to find a solution and I'm running out of time. Thanks!
This is my implementation so far:
DetailsNavigation.js
const DetailsNavigation = ({ route }) => {
return (
<Tab.Navigator
tabBarOptions={{
activeBackgroundColor: colors.primary,
activeTintColor: colors.secondary,
inactiveBackgroundColor: colors.secondary,
inactiveTintColor: colors.primary,
labelStyle: {
fontSize: 13,
marginBottom: 5,
},
}}
>
<Tab.Screen
name="DetailsScreen"
options={{
title: "Portfolio",
tabBarIcon: ({ color, size }) => (
<MaterialIcons name="account-box" size={24} color={color} />
),
}}
children={() => <DetailsScreen worker={route.params} />}
/>
<Tab.Screen
name="RatingScreen"
component={RatingScreen}
options={{
title: "Bewertungen",
tabBarIcon: ({ color, size }) => (
<MaterialIcons name="star" size={24} color={color} />
),
}}
/>
</Tab.Navigator>
);
};
export default DetailsNavigation;
DetailsNavigation.js is implemented here:
WorkersNavigation.js
const WorkersNavigation = (props) => {
return (
<Stack.Navigator>
<Stack.Screen
name="WelcomeScreen"
component={WelcomeScreen}
options={{ headerShown: false }}
></Stack.Screen>
<Stack.Screen
name="WorkersScreen"
component={WorkersScreen}
options={{ headerShown: false }}
></Stack.Screen>
<Stack.Screen
name="DetailsNavigation"
component={DetailsNavigation}
options={{ headerShown: false }}
></Stack.Screen>
</Stack.Navigator>
);
};
export default WorkersNavigation;
The white space found on iPhone X devices and above is called the Safe Area and exists to ensure appropriate insetting based on the device and context. Refer to the official Human Interface Guidelines for more information.
The react-navigation's BottomTabNavigator supports safe areas out-of-the-box for the default BottomTabBar, so in order to remove the SafeArea under it, you need to override the settings provided for the BottomTabNavigator.
<Tab.Navigator
tabBarOptions={ {
...
safeAreaInsets: {
bottom: 0,
},
} }
>
...
</Tab.Navigator>
I think you are wrap outside of WorkersNavigation like this
<SafeAreaView>
<WorkersNavigation />
</SafeAreaView>
screenOptions={({route}) => ({
tabBarStyle: {backgroundColor: '#436332', borderTopColor: '#23321A'},
tabBarLabelStyle: {
fontWeight: '600',
fontSize: 12,
},
tabBarActiveTintColor: '#f1c522',
tabBarInactiveTintColor: '#f4f1de',
tabBarActiveBackgroundColor: '#436332',
tabBarInactiveBackgroundColor: '#436332',
})}
Add this lines at your TabNavigator screenOptions:
tabBarItemStyle: {borderWidth: 1, borderColor:'#101010'},
tabBarStyle: {paddingBottom:0, backgroundColor: '#101010'},
and if you use <SafeAreaView>, delete it.
In my case for remove bottom space I need to set the height for tabBarStyle and also for tabBarItemStyle:
<Tab.Navigator
initialRouteName={ScreenNames.Home}
screenOptions={{
tabBarItemStyle: {
height: 53,
},
tabBarStyle: {
height: 53,
},
}}>
For remove upper white space:
<Tab.Navigator
initialRouteName={ScreenNames.Home}
screenOptions={{
tabBarStyle: {
borderTopWidth: 0,
elevation: 0,
},
}}>
I have an app that is composed of a tabbed navigation with 5 screens and one of them is a stack navigation of two screens. On one of the two stack screens I want to hide the bottom tabs. How can I do that ?
I already checked React Navigation V5 Hide Bottom Tabs but when I tried using navigation.setOptions({ tabBarVisible: false }) it changed the options for the stack navigator not the tab one.
Here is my code
// Screen where I want to hide the BottomTabNavigator
function StackSecondScreen({ navigation }) {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "indianred"
}}
>
<Text>StackSecondScreen</Text>
</View>
);
}
const Stack = createStackNavigator();
function TabFirstScreen({ navigation }) {
return (
<Stack.Navigator initialRouteName="StackFirst">
<Stack.Screen
name="StackFirst"
component={StackFirstScreen}
options={{
headerShown: false
}}
/>
<Stack.Screen name="StackSecond" component={StackSecondScreen} /> // <== Screen where I want to hide the BottomTabNavigator
</Stack.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator initialRouteName="First">
<Tab.Screen name="TabFirst" component={TabFirstScreen} />
<Tab.Screen name="TabSecond" component={TabSecondScreen} />
<Tab.Screen name="TabThird" component={TabThirdScreen} />
<Tab.Screen name="TabFourth" component={TabFourthScreen} />
<Tab.Screen name="TabFifth" component={TabFifthScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}