React-navigation stack horizontal screen gesture for Android. (react-navigation/stack) - react-native

On Android, I am aware that the stack screen animation can be controlled to be horizontal when using the react-navigation-stack library with the transitionConfig prop. However, it doesn't seem to work for the react-navigation/stack library, or rather it doesn't have any support for it. Have anyone managed to make it work with react-navigation/stack? Or are there any way to combine both libraries, as i would find it a waste to rewrite my codes in another library just for this small issue. Any help would be appreciated!

Use it like this -
Working Example
Youtube Tutorial for Navigation Gestures
import * as React from 'react';
import { Button, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { Easing } from 'react-native';
import {
createStackNavigator,
CardStyleInterpolators,
} from '#react-navigation/stack';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Go to Profile"
onPress={() => navigation.navigate('Profile')}
/>
</View>
);
}
function ProfileScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Go to Notifications"
onPress={() => navigation.navigate('Notifications')}
/>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
const Stack = createStackNavigator();
const timingConfig = {
animation: 'timing',
config: {
duration: 200,
easing: Easing.linear,
},
};
const options = {
gestureEnabled: true,
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
transitionSpec: {
open: timingConfig,
close: timingConfig,
},
};
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} options={options} />
<Stack.Screen
name="Notifications"
component={NotificationsScreen}
options={options}
/>
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={options}
/>
<Stack.Screen
name="Settings"
component={SettingsScreen}
options={options}
/>
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}

Related

What is the proper way to have only one header with Open Drawer and Back button?

What I need is a single header with a back button on StackScreen2 and a toggle drawer button in StackScreen1.
I apologise for my poor writing and English.
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
function StackScreen1({ navigation }) {
return (
<View>
<Text>StackScreen1</Text>
<Button title="Go To StackScreen2" onPress={() => navigation.navigate("StackScreen2")} />
</View>
)
}
function StackScreen2() {
return (
<View>
<Text>StackScreen2</Text>
</View>
)
}
function DrawerScreen1() {
return (
<Stack.Navigator>
<Stack.Screen name="StackScreen1" component={StackScreen1} />
<Stack.Screen name="StackScreen2" component={StackScreen2} />
</Stack.Navigator>
)
}
function DrawerScreen2() {
return (
<View>
<Text>DrawerScreen2</Text>
</View>
)
}
const Drawer = createDrawerNavigator();
export default function Test3() {
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="DrawerScreen1" component={DrawerScreen1} />
<Drawer.Screen name="DrawerScreen2" component={DrawerScreen2} />
</Drawer.Navigator>
</NavigationContainer>
);
}
StackScreen1
StackScreen2
I tried hiding drawer header but then I don't have toggle drawer button anywhere.
Check below code for drawer navigation:
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => navigation.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator useLegacyImplementation initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
You can check more about drawer here.
May be this will help you!
import * as React from 'react';
import { Ionicons, FontAwesome } from '#expo/vector-icons';
import { Button, View, Text, Pressable,Image } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createDrawerNavigator } from '#react-navigation/drawer';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('SettingsScreen')}
/>
</View>
);
}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.goBack()}
/>
</View>
);
}
const Drawer = createDrawerNavigator();
function MyDrawer() {
return (
<Drawer.Navigator
useLegacyImplementation
// screenOptions={{
// drawerLabelStyle: { fontSize: 17, color: '#000',marginLeft:-30 }
// }}
>
<Drawer.Screen
name="HomeScreen"
component={DetailsScreen}
screenOptions={{
headerShown: false,
}}
/>
</Drawer.Navigator>
);
}
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen
name="SettingsScreen"
component={MyDrawer}
options={{
headerShown: false,
tabBarIcon: ({ color, size }) => (
<Ionicons name="md-home" size={24} color={'#eee'} />
),
tabBarStyle: { position: 'absolute' },
tabBarActiveTintColor: '#eee',
tabBarInactiveTintColor: '#eee',
}}
/>
<Tab.Screen
name="DetailsScreen"
component={DetailsScreen}
options={{
headerShown: false,
tabBarIcon: ({ color, size }) => (
<Image source={{uri:"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTUAN0zLcvLFjdaYN1dBRSKoIuJndRW6VuX85w2yzEzxvTwO3B0Y_gv1x8kVDISNKJEbq0&usqp=CAU"}}
style={{width:24,height:24,borderRadius:24}} />
),
tabBarStyle: { position: 'absolute' },
tabBarActiveTintColor: '#eee',
tabBarInactiveTintColor: '#eee',
}}
/>
</Tab.Navigator>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>2</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="HomeScreen">
<Stack.Screen
name="HomeScreen"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="SettingsScreen"
component={MyTabs}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;

React Native Expo app showing two topbars

I'm following this example: https://reactnavigation.org/docs/tab-based-navigation#a-native-stack-navigator-for-each-tab
I've copy pasted the example from the website. However, this is what I see:
I've the following packages in package.json:
"#react-navigation/bottom-tabs": "^6.0.9",
"#react-navigation/native": "^6.0.6",
"#react-navigation/native-stack": "^6.2.5",
"#react-navigation/stack": "^6.0.11",
Here's my code:
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import Ionicons from '#expo/vector-icons/Ionicons';
function DetailsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function AnalyticsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Analytics screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
const HomeStack = createNativeStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="HomeScreen" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createNativeStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="SettingsScreen" component={SettingsScreen} />
<SettingsStack.Screen name="Details" component={DetailsScreen} />
</SettingsStack.Navigator>
);
}
const AnalyticsStack = createNativeStackNavigator();
function AnalyticsStackScreen() {
return (
<AnalyticsStack.Navigator>
<AnalyticsStack.Screen name="Analytics" component={SettingsScreen} />
<AnalyticsStack.Screen name="Details" component={DetailsScreen} />
</AnalyticsStack.Navigator>
)
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = 'home';
} else if (route.name === 'Settings') {
iconName = 'search';
} else if (route.name === 'Analytics') {
iconName = 'bar-chart'
}
// You can return any component that you like here!
return <Ionicons name={iconName} size={size} color={color} />;
},
tabBarActiveTintColor: 'tomato',
tabBarInactiveTintColor: 'gray',
})}
>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
<Tab.Screen name="Analytics" component={AnalyticsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
You can easily hide navigator headers like this:
<YourNavigator.Navigator
screenOptions={{ headerShown: false /* <-- This will hide your header */ }}
>
<YourNavigator.Screen
name='Settings' /* <-- This name will be shown as header if true */
component={YourSettingsNavigator}
/>
</YourNavigator.Navigator>
Since YourSettingsNavigator is another Navigator, you are nesting navigators in each other. When doing this make sure to set headerShown: false in at least one of the navigators or you get two headers.

React Navigation V6 Bottom Tab Not Displaying

I'm following the guide here from React Navigation V6 and my component is not displaying as it is intended to. When I swap out createBottomTabNavigator with createMaterialTopTabNavigator I get my display. Can somebody help me figure out why the output is behaving this way? Photos are attached below the code. Thank you to anybody that can help!
Edit: React-Native-Web sometimes displays things incorrectly. When viewed on a phone it looks correct.
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
function FeedScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Feed Screen!</Text>
</View>
);
}
function HomeScreen({ navigation }:any) {
return (
<View >
<Text>Home screen</Text>
<Button
title="Go to Profile"
onPress={() => navigation.navigate('Profile')}
/>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function NotificationsScreen({ navigation }:any) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Notifications Screen</Text>
</View>
);
}
function ProfileScreen({ navigation }:any) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Profile Screen</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function SettingsScreen({ navigation }:any) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to tabs"
onPress={() => navigation.navigate('Home')}
/>
</View>
);
}
function BasicStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
options={{ headerShown: true }}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
)
}
function Home() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Feed" component={FeedScreen} />
<Tab.Screen name="Notifications" component={NotificationsScreen} />
</Tab.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<BasicStack/>
</NavigationContainer>
);
}
Output with createBottomTabNavigator
Output with createMaterialTopTabNavigator

How to always Show Bottom Tabs Label in React Native Navigation V5?

return (
<Tab.Navigator
barStyle={{backgroundColor: '#F2F2F2'}}
initialRouteName="Catalog">
<Tab.Screen
name="Settings"
options={{
tabBarLabel: 'Alterações',
title: 'Configurações',
tabBarIcon: ({color}) => (
<MaterialCommunityIcons name="cog" color="#000" size={22} />
),
}}>
{(props) => (
<Settings
{...props}
params={{
cpf: params.cpf ? params.cpf : cpf,
}}
/>
)}
</Tab.Screen>
<Tab.Screen
name="Catalog"
options={{
tabBarVisible: false,
title: 'Ofertas',
}}>
{(props) => (
<Catalog
{...props}
params={{
pracaId: params.pracaId ? params.pracaId : pracaId,
}}
/>
)}
</Tab.Screen>
[...]
</Tab.Navigator>
);
The documentations says to use the titleDisplayMode but where? when? I only find solution for older versions. I need it to v5.
Please, can some one help me?
I have include some part of my code to understend how I'm using the lib
There is a shifting prop that you can put to false in your navigator :
<Tab.Navigator
barStyle={{backgroundColor: '#F2F2F2'}}
initialRouteName="Catalog"
shifting={false}
>
.....
Whether the shifting style is used, the active tab icon shifts up to show the label and the inactive tabs won't have a label.
By default, this is true when you have more than 3 tabs. Pass shifting={false} to explicitly disable this animation, or shifting={true} to always use this animation.
https://reactnavigation.org/docs/5.x/material-bottom-tab-navigator#shifting
I have created this example where the HomeScreen always hide the bottom tab and the SettingsStack always show the bottom tab automatically. The key point is basically these lines of code, one have just a screen and the other one have a StackNavigator:
<Tab.Screen name="HomeScreen" component={HomeScreen} />
<Tab.Screen name="SettingsStack" component={SettingsStack} />
This example is similar to the one in the docs https://reactnavigation.org/docs/hiding-tabbar-in-screens/, but with more components.
The code below is in snack, check if this helps you:
https://snack.expo.io/#ronicesarrc/react-navigation-hiding-showing-bottom-tab-navigator
import React from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
function SettingsInternalScreen() {
return (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'orange',
}}>
<Text>SettingsInternalScreen!</Text>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'red',
}}>
<TouchableOpacity
style={{ backgroundColor: 'orange', padding: 16 }}
onPress={() => navigation.navigate('SettingsInternalScreen')}>
<Text>Go to Screen showing bottom tab</Text>
</TouchableOpacity>
</View>
);
}
const SettingStack = createStackNavigator();
function SettingsStack() {
return (
<SettingStack.Navigator>
<SettingStack.Screen name="SettingsScreen" component={SettingsScreen} />
<SettingStack.Screen
name="SettingsInternalScreen"
component={SettingsInternalScreen}
/>
</SettingStack.Navigator>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity
style={{ backgroundColor: 'gray', padding: 16 }}
onPress={() => navigation.navigate('HomeInternalScreen')}>
<Text>Go to Screen hidding bottom tab</Text>
</TouchableOpacity>
</View>
);
}
function HomeInternalScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>HomeInternalScreen!</Text>
</View>
);
}
const Tab = createMaterialBottomTabNavigator();
const Tabs: React.FC = () => {
return (
<Tab.Navigator>
<Tab.Screen name="HomeScreen" component={HomeScreen} />
<Tab.Screen name="SettingsStack" component={SettingsStack} />
</Tab.Navigator>
);
};
const MainStack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<MainStack.Navigator headerMode="none">
<MainStack.Screen name={'Tabs'} component={Tabs} />
<MainStack.Screen
name={"HomeInternalScreen"}
component={HomeInternalScreen}
/>
</MainStack.Navigator>
</NavigationContainer>
);
}

How can I access a current navigation inside a React.Component using reactnavigation 5?

I'm now using react-navigation version 5 following an expo tutorial to navigate to another screen inside a Stack (embedded in a Tab Navigator).
In the tutorial, they always used a function to init a specific screen so the navigation parameter will easy to be called inside the function's body.
Eg:
function HomeScreen({ navigation })
//Called
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
But, if I construct a React.Component instead, how can I access the navigation inside that Component to navigate to another component? plz
Please run the codes bellow on expo if my explanations are bad.
Thanks,
import * as React from 'react';
import { Button, Text, View, Alert } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
class Options extends React.Component {
navigaeToAnotherScreen() {
console.log('How can I access current navigation plz?');
}
render() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Hello, world! Option</Text>
<Button title="Go To Main" onPress={() => this.navigaeToAnotherScreen() }/>
</View>
);
}
}
function OptionsScreen({ navigation }) {
return (
<Options/>
);
}
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
<Button title="Detail" onPress={ () => navigation.push('Options')}/>
</View>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.push('Details')}
/>
</View>
);
}
const HomeStack = createStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
<HomeStack.Screen name="Options" component={OptionsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Details" component={DetailsScreen} />
</SettingsStack.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
try this
I noticed you didn't pass existing props to Options
function OptionsScreen({ navigation }) {
return (
<Options navigation={navigation} />
);
then try this
navigaeToAnotherScreen() {
this.props.navigation.navigate("AnyScreen");
}