Custom TabBarIcon hidden under DrawerNavigator - React Navigation v5 - react-native

I am having this issue where a custom made TabBarIcon is not showing fully. I have read the docs, github to try and find a solution for this.
What I could make out was that nesting a BottomTabsNavigator in a DrawerNavigator might have repercussions, please correct me if I'm wrong.
This is how my Navigation Container would look like
AppNavigator
Authenticated ? DrawerNavigator : AuthNavigator
// Inside DrawerNavigator:
DrawerNavigator
BottomTabsNavigator
Rest of the screens
An image for illustration of my problem:
AppNavigator.js:
// AppNav uses StackNavigation
<NavigationContainer>
<Navigator headerMode='none'>
{authenticated && !isLoading ? (
<Screen name='DrawerNavigator' component={DrawerNavigator} />
) : !authenticated && !isLoading ? (
<Screen name='AuthNavigator' component={AuthNavigator} />
) : (
<Screen name='Loading' component={LoadingScreen} />
)}
</Navigator>
</NavigationContainer>
DrawerNavigator.js:
// I am using a UI library, UI kitten for the Drawer. But I don't think this is the cause
const { Navigator, Screen } = createDrawerNavigator();
const DrawerNavigator = () => (
<Navigator
drawerContent={props => <DrawerContent {...props} />}
initialRouteName='BottomTabsNavigator'
>
<Screen name='BottomTabsNavigator' component={BottomTabsNavigator} />
<Screen name='ChangePassword' component={ChangePasswordScreen} />
<Screen name='AuthNavigator' component={AuthNavigator} />
<Screen name='UserProfile' component={UserProfileScreen} />
<Screen name='EditProfile' component={EditProfileScreen} />
<Screen name='ActivityFeed' component={ActivityFeedScreen} />
</Navigator>
);
BottomTabsNavigator.js:
const BottomTabs = createBottomTabNavigator();
const BottomTabsNavigator = ({ navigation }) => {
return (
<BottomTabs.Navigator
tabBarOptions={{
showLabel: false,
activeTintColor: '#407BFF'
}}
initialRouteName='Home'
>
<BottomTabs.Screen
name='Home'
component={MainAppScreen}
options={{
tabBarIcon: Some Icon
}}
/>
<BottomTabs.Screen
name='TeamUp'
component={TeamUpScreen}
options={{
tabBarIcon: () => <TeamUpBottomTab navigation={navigation} /> // Custom made 'Icon'
}}
/>
<BottomTabs.Screen
name='ChatOverview'
component={ChatOverviewScreen}
options={{
tabBarIcon: Some Icon
}}
/>
</BottomTabs.Navigator>
);
};
The custom made Icon is as such:
import { Platform, Pressable, StyleSheet, Animated, Image } from 'react-native';
<Pressable onPress={pressHandler} style={styles.teamUp}>
<Animated.View style={[{ transform: [{ scale: animatedScale }] }]}>
<Image
style={styles.logo}
source={require('../../assets/images/orbital-logo.png')}
/>
</Animated.View>
</Pressable>
Been stuck for a few days, and searching for a solution isn't helping much.
Appreciate any help, thank you

Related

How to add clickable Icons to reactNative navbar

I want to add clickable icons to my reactnative header component
Currently it looks like this
next to the title text on the right I want to add an audio symbol but i cant figure out on doing this.
I have seen plenty of answers that work with navigation but Im using drawers so i dnt understand how to add icons.
This is what my code looks like
app.js
<NavigationContainer >
<Drawer.Navigator initialRouteName="MetalDetector" screenOptions={{
drawerStyle: {
backgroundColor: '#3e4463',
width: 220
},
}}>
<Drawer.Screen name="MetalDetector" component={Home} options={{drawerLabel: '๐Ÿ”ฆ MetalDetector'}} />
<Drawer.Screen name="Settings" component={Settings} options={{drawerLabel: '๐Ÿ›  Settings'}} />
<Drawer.Screen name="Calibrate" component={Home} options={{drawerLabel: '๐Ÿ’ก Calibration'}}/>
<Drawer.Screen name="Feedback" component={Home} options={{drawerLabel: '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Feedback'}}/>
and this is my home.js file which renders content for the metaldetector page
<View style={styles.container}>
<View style={styles.buttonContainer}>
//Cde is below
</View>
</View>
);
}
So where would i add icons to the titlemenu?
I found this here, which covers on how to set the header using stackscreen
https://reactnavigation.org/docs/headers/
but since I use drawer.screen i dont know how to apply that
Option 1:
The DrawerContent file
import React, { useState } from 'react';
import { View, StyleSheet, Image, Alert, Text } from 'react-native';
import { Title, Drawer } from 'react-native-paper';
import { DrawerContentScrollView, DrawerItem } from '#react-navigation/drawer';
import { FontAwesome, MaterialIcons, AntDesign, Ionicons } from '#expo/vector-icons';
import colors from '../config/colors';
const AppDrawerItem = ({ label , icon, onPress, ...props }) => {
return (
<DrawerItem
icon={icon}
label={label}
onPress={onPress}
/>
);
}
export function DrawerContent(props) {
return (
<View style={{ flex: 1 }}>
<DrawerContentScrollView {...props}>
<Drawer.Section style={styles.drawerSection}>
<AppDrawerItem
onPress={() => { setIsDeletePressed(false); props.navigation.navigate('Dashboard') }}
label="Dashboard"
icon={({ color, size, focused }) => (
<MaterialIcons
name="dashboard"
color={focused ? colors.primary : color}
size={size}
/>
)}
{...props}
/>
<AppDrawerItem
onPress={() => { setIsDeletePressed(false); props.navigation.navigate('Messages') }}
label="Messages"
icon={({ color, size, focused }) => (
<MaterialIcons
name="notifications"
color={focused ? colors.primary : color}
size={size}
/>
)}
{...props}
/>
</Drawer.Section>
</DrawerContentScrollView >
</View >
);
}
DrawerNavigator
<Drawer.Navigator
screenOptions={{
headerTitleStyle: {
color: "black",
opacity: 0.9
},
headerTintColor: colors.primary,
swipeEnabled: false,
headerTitleAlign: 'center',
headerShadowVisible: false,
}} drawerContent={props => <DrawerContent {...props} />} > //---here you can add drawercontent component
<Drawer.Screen name="Dashboard" component={HomeScreen} />
<Drawer.Screen options={{ headerShown: true }} name="Messages" component={NotificationNavigator} />
</Drawer.Navigator >
Edit:
Option2:
You can add the icon in the <Drawer.Screen> tag.
<Drawer.Screen name="Feed" component={Feed} options={{
title: 'Home',
drawerIcon: ({focused, size}) => (
<Ionicons
name="md-home"
size={size}
color={focused ? '#7cc' : '#ccc'}
/>
),
}} />

React Native Top Area View

I'm new to React Native and I have a very simple first page that I'm testing out. My only thing I'm having a hard time understanding is where there is a Title view at the top area. Here's what my app currently looks like https://i.stack.imgur.com/H7vbO.png As you can see, there's that huge white space that has "Home" in it. I'm trying to get rid of it completely and just have the my background color throughout the whole thing. My only problem is that I don't even know where that is coming from. Here is my code and thank you.
This is my HomeScreen
import React from "react";
import { StyleSheet, Text, SafeAreaView, Platform } from "react-native";
import { StatusBar } from "expo-status-bar";
const HomeScreen = ({}) => {
return (
<SafeAreaView style={styles.container}>
<Text style={{ color: "white" }}>Home Screen</Text>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#4B4B4B",
alignItems: "center",
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0,
},
});
export default HomeScreen;
This is my App.js
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import MainTabScreen from "./screens/MainTabScreen";
const Stack = createNativeStackNavigator();
const App = () => {
return (
<NavigationContainer>
<MainTabScreen />
</NavigationContainer>
);
};
export default App;
Here is my MainTabScreen
import React from "react";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import Icon from "react-native-vector-icons/Ionicons";
import HomeScreen from "./HomeScreen";
import SearchScreen from "./SearchScreen";
import InboxScreen from "./InboxScreen";
import AccoutScreen from "./AccountScreen";
const Tab = createBottomTabNavigator();
const MainTabScreen = () => {
return (
<Tab.Navigator initialRouteName="Home" activeColor="#000000">
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: ({ color }) => (
<Icon name="ios-home" color={color} size={26} />
),
}}
/>
<Tab.Screen
name="Search"
component={SearchScreen}
options={{
tabBarIcon: ({ color }) => (
<Icon name="ios-search" color={color} size={26} />
),
}}
/>
<Tab.Screen
name="Inbox"
component={InboxScreen}
options={{
tabBarIcon: ({ color }) => (
<Icon name="ios-chatbox" color={color} size={26} />
),
}}
/>
<Tab.Screen
name="Account"
component={AccoutScreen}
options={{
tabBarIcon: ({ color }) => (
<Icon name="ios-person" color={color} size={26} />
),
}}
/>
</Tab.Navigator>
);
};
export default MainTabScreen;
P.S.: I already tried changing SafeAreaView to just View, and I also try removing the padding top
That view is actually the header of the navigator. Thus, to remove it, on your main navigator, set headerShown: false.
In your mainTabScreen;
<Tab.Navigator screenOptions={{headerShown: false}} initialRouteName="Home" activeColor="#000000">
...
Rest will be same.
Bottom tab accepts header related options in options property of Navigator Screens and screenOptions property in The Navigator Component
e.g
const MainTabScreen = () => {
return (
<Tab.Navigator
initialRouteName="Home"
activeColor="#000000"
// To remove header from all screens,
// screenOptions={{ headerShown: false }}
>
<Tab.Screen
name="Home"
component={Home}
options={{
tabBarIcon: ({ color }) => (
<Icon name="ios-home" color={color} size={26} />
),
// Update Header Title
// headerTitle: 'NOT A HOME',
}}
/>
<Tab.Screen
name="Search"
component={Home}
options={{
tabBarIcon: ({ color }) => (
<Icon name="ios-search" color={color} size={26} />
),
}}
/>
</Tab.Navigator>
);
};
You can read about all header related options in - https://reactnavigation.org/docs/elements#header

React Native: where to place Navigators for other screens?

My Application has a BottomTabNavigator, each Tab is linked to a component, which is a StackNavigator.
With that implementation, I can easily switch between the tab screens and also see a detailed screen.
Here is the code of my Screen component:
export default function Screen ({props, children}) {
return (
<>
<Stack.Navigator
screenOptions={{
cardShadowEnabled: false,
header: (props) => {
return <Header {...props} />
},
}}
>
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
<SafeAreaView style={styles.screen}>
<View style={styles.container}>{ children }</View>
</SafeAreaView>
<TabNavigator i18n={i18n}/>
</>
);
}
In the header component, I have an Icon, which onPress needs to navigate to the SettingsScreen.
I am afraid that I am not sure if this is the right implementation of the SettingsNavigator and if yes, how is possible on click on my header menu to navigate to the SettingsScreen.
Here is my Header.js code:
export default function Header (props, navigation) {
...
return (
<View style={styles.container}>
<View style={styles.link} onPress={navigation.navigate("Settings")}>
<MaterialCommunityIcons name="tune" size={32} />
</View>
</View>
)
};
I get an error:
TypeError: navigation.navigate is not a function.(In
'navigation.navigate("Settings")', 'navigation.navigate' is undefined)
How can I access the navigation from my Header component?
I don't think it's a correct implementation.
Please try like following
<Stack.Navigator
initialRouteName={Routes.SignIn}
screenOptions={{
cardShadowEnabled: false,
header: (props) => {
return <Header {...props} />
},
}}
>
<Stack.Screen name={Routes.SignIn} component={SignInScreen} />
<Stack.Screen name={Routes.ForgotPassword} component={ForgotPasswordScreen} />
<Stack.Screen name={Routes.SignUp} component={SignUpScreen} />
</Stack.Navigator>

How can I hide the bottom tab bar on a specific screen (react navigation 5.x)

I wanted to know how to hide the bottom tab bar from a specific screen inside my stack navigator, my code is below. I just want to hide bottom tabs for the Player screen, or open Player screen with modal can anyone help me?
This is my code for my main tab navigator
import React from 'react';
import { StatusBar } from 'react-native';
import { NavigationContainer, DarkTheme } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
//views
import HomeStack from './src/views/Home';
import SearchStack from './src/views/Search';
import MoviesStack from './src/views/Movies';
import SeriesStack from './src/views/Series';
import Other from './src/views/Other';
//icons
import {
HomeIcon,
SearchIcon,
MovieIcon,
SeriesIcon,
OtherIcon,
} from './src/components/icons';
const Tab = createBottomTabNavigator();
export default function App() {
return (
<>
<StatusBar barStyle="dark-content" />
<NavigationContainer theme={DarkTheme}>
<Tab.Navigator
initialRouteName="Home"
tabBarOptions={{
activeTintColor: 'white',
keyboardHidesTabBar: false,
}}
>
<Tab.Screen
name="Home"
component={HomeStack}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<HomeIcon
fill={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
<Tab.Screen
name="Search"
component={SearchStack}
options={{
tabBarLabel: 'Search',
tabBarIcon: ({ focused }) => (
<SearchIcon
stroke={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
<Tab.Screen
name="Movie"
component={MoviesStack}
options={{
tabBarLabel: 'Movie',
tabBarIcon: ({ focused }) => (
<MovieIcon
color={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
<Tab.Screen
name="Series"
component={SeriesStack}
options={{
tabBarLabel: 'Series',
tabBarIcon: ({ focused }) => (
<SeriesIcon
color={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
<Tab.Screen
name="Other"
component={Other}
options={{
tabBarLabel: 'Other',
tabBarIcon: ({ focused }) => (
<OtherIcon
fill={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
</Tab.Navigator>
</NavigationContainer>
</>
);
}
This is my code for my main stack navigator
import React from 'react';
import { View, Image } from 'react-native';
import { createStackNavigator } from '#react-navigation/stack';
//components
import Screen from '../components/Screen';
import HomeList from '../components/HomeList';
//views
import MovieDetail from './MovieDetail';
import SeriesDetail from './SeriesDetail';
import Player from './Player';
function Home({ navigation }) {
return (
<Screen>
<View>
<Image source={require('../../assets/logo.png')} />
...
</View>
</Screen>
);
}
const Stack = createStackNavigator();
export default function HomeStack() {
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="MovieDetail" component={MovieDetail} />
<Stack.Screen name="SeriesDetail" component={SeriesDetail} />
<Stack.Screen name="Player" component={Player} />
</Stack.Navigator>
);
}
and this is my code for stack navigator of the page I use to send data to the page i want to hide
import React from 'react';
import {
View,
Text,
TouchableOpacity,
} from 'react-native';
//components
import Screen from '../components/Screen';
import Loading from '../components/Loading';
export default function MovieDetail({ route, navigation }) {
const { id, title } = route.params;
return (
<Screen>
<TouchableOpacity
activeOpacity={0.7}
onPress={() =>
navigation.navigate('Player', {
uri: 'https://blabla.com',
})
}
>
<PlayIcon color="black" />
<Text>
Play
</Text>
</TouchableOpacity>
</Screen>
);
}
and here I want to hide tab bar this screen
import React from 'react';
import WebView from 'react-native-webview';
export default function Player({ route }) {
const { uri } = route.params;
return (
<WebView source={{ uri }} />
);
}
Ciao, you can hide bottom tabbar in Player screen like that:
Modify your Tab.Screen Home like this:
<Tab.Screen
name="Home"
component={HomeStack}
options={({ route }) => ({
tabBarLabel: 'KeลŸfet',
tabBarIcon: ({ focused }) => (
<HomeIcon
fill={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
tabBarVisible: getTabBarVisibility(route),
})}
/>
Then create getTabBarVisibility function to check that the name of the root is Player:
const getTabBarVisibility = (route) => {
const routeName = route.state
? route.state.routes[route.state.index].name
: '';
if (routeName === 'Player') {
return false;
}
return true;
};
That's it. Now if you navigate into Player page, tabBar disappears.

How to call toggleDrawer in React Navigation 5

I got a React-Navigation 5 drawer menu working using gesture, but I also want to add an icon on the right side of the header to toggle the drawer menu.
I have the navigation setup in my App.js like this:
import {NavigationContainer, DrawerActions} from '#react-navigation/native';
//....... other imports
const HomeStack = createStackNavigator();
const HomeStackScreens = () => (
<HomeStack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: '#5C6BC0',
},
headerTintColor: '#fff',
headerRight: () => {
return (
<TouchableOpacity
onPress={() => DrawerActions.toggleDrawer()}>
<Icon name="bars" color="#FFF" size={18} />
</TouchableOpacity>
);
},
}}>
<HomeStack.Screen
name="Home"
component={HomeScreen}
options={{
header:({scene, previous, navigation}) => {
return (
<TouchableOpacity onPress={() => navigation.toggleDrawer()}>
<Icon name="bars" color="#FFF" size={18} />
</TouchableOpacity>
);
}
}}
/>
<HomeStack.Screen name="Login" component={Login} />
<HomeStack.Screen name="Register" component={Register} />
</HomeStack.Navigator>
);
const ProfileStack = createStackNavigator();
const ProfileStackScreens = () => (
<ProfileStack.Navigator>
<ProfileStack.Screen name="Profile" component={Profile} />
</ProfileStack.Navigator>
);
const SettingStack = createStackNavigator();
const SettingStackScreens = () => (
<SettingStack.Navigator>
<SettingStack.Screen name="Profile" component={Profile} />
</SettingStack.Navigator>
);
const Drawer = createDrawerNavigator();
const DrawerScreens = () => (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={HomeStackScreens} />
<Drawer.Screen name="Profile" component={ProfileStackScreens} />
<Drawer.Screen name="Settings" component={SetttingStackScreens} />
</Drawer.Navigator>
);
class MyApp extends React.Component {
render() {
return (
<NavigationContainer>
<DrawerScreens />
</NavigationContainer>
);
}
}
export default MyApp;
All my others screen are in the form "export default class ScreenName extends React.Component". They are imported in App.js to setup the navigation. The initial screen is Home. The icon is showing correctly on the right side of the header. Calling "DrawerActions.toggleDrawer()" directly does nothing.
I tried "this.props.navigation.toggleDrawer()", and it throws error because "this.props" is undefined.
How can I invoke toggleDrawer() with such a navigation setup? Any help is really appreciated!
Here is the final solution I come up with that requires minimal changes to my original code. The key is to receive "navigation" in screenOptions or options, then I can call navigation methods in the children of screenOptions/options.
<HomeStack.Navigator
screenOptions={({navigation}) => ({
headerStyle: {
backgroundColor: '#5C6BC0',
},
headerTintColor: '#fff',
headerRight: () => {
return (
<TouchableOpacity
style={{paddingRight: 8}}
onPress={() => navigation.toggleDrawer()}>
<Icon name="bars" color="#FFF" size={18} />
</TouchableOpacity>
);
},
})}>