I have spend more than si hours trying to change the background of the DrawerNavigator to transparent without any success.
When I write
when I change it in the main component it works
const MainTabBarDrawer = DrawerNavigator({
Home:{
screen:MainTabNavigator,
},
},{
drawerWidth: 200,
drawerPosition: 'right',
// contentComponent: props => <Text style={{color:'white'}} >text
</Text>,
drawerBackgroundColor: 'yellow',
//backgroundColor:'transparent',
// style: {
// //backgroundColor: 'transparent',
// flex: 1
// },
// contentOptions: {
// style: {
// backgroundColor: 'transparent',
// flex: 1
// }
},
{
style: {
backgroundColor: 'transparent',
flex:1
}
}
)
class App extends Component{
render()
{
return(<MainTabBarDrawer style={{backgroundColor: 'transparent'}}/>)
//return(<Login/>)
}
}
While the above approach will work my layout is much complex and I don't want the drawer to appear in all my views.
So dose any body know If I can change the background of the DrawerNavigator directly without rendering it as a component?
In React Navigation 5, this would be:
<Drawer.Navigator
initialRouteName={...}
drawerContent={...}
drawerStyle={{backgroundColor: 'transparent'}}
>
Add drawerBackgroundColor: "transparent" to drawerConfig.
I think you are looking for drawerContentOptions or drawerStyle of Drawer.Navigator
<NavigationContainer>
<Drawer.Navigator
..........
drawerPosition="left"
drawerContentOptions={{
activeBackgroundColor:"transparent", //here change it
}}
drawerStyle={{backgroundColor: 'transparent'}} //or here
initialRouteName="Splash">
<Drawer.Screen
name="HomePage"
component={StackScreen}
options={{
drawerLabel: () => {return null},
title:null,
drawerIcon: () => {return <AppIconImage/>}
}}
/>
</Drawer.Navigator>
</NavigationContainer>
The issue was fixed since I have updated to the latest version
1.0.0-beta.16
Adding the style backgroundColor: 'transparent' to drawerStyle inside the screenOptions param of Drawer.Navigator worked for me.
import React from 'react';
import {createDrawerNavigator} from '#react-navigation/drawer';
import CustomDrawer from '../components/Drawer';
const Drawer = createDrawerNavigator();
const DrawerNavigator = () => {
return (
<Drawer.Navigator
initialRouteName="Stack"
screenOptions={{
headerShown: false,
drawerStyle: {width: '80%', backgroundColor: 'transparent'}, // Add this.
}}
drawerContent={props => <CustomDrawer {...props} />}>
// Screens that go inside the navigator.
</Drawer.Navigator>
);
};
export default DrawerNavigator;
P.S.: I am using #react-navigation/drawer: ^6.5.0.
For ReactNavigation Version 6.
try
<Drawer.Navigator
initialRouteName={...}
drawerContent={...}
screenOptions={{
drawerStyle: {
backgroundColor: 'transparent',
},
}}>
Adding React Docs link for reference.
https://reactnavigation.org/docs/drawer-navigator#drawerstyle
Related
I have BottomTab navigator with 2 screens Home and Activity, nested inside a Drawer Navigator. When I switch from one screen to second one using BottomTab, my header of Drawer Navigator hides with flickering effect and same thing happens again when I show it up on previous screen. I am handling headerShown:true and headerShown:false in listeners prop of Tab.Screen using focus and blur of that screen.
It seems like header is rendering after rendering of components below it. This header showing and hiding has more delay if I have multiple components inside both screens.
Snack repo is attached.
https://snack.expo.dev/#a2nineu/bottomtab-inside-drawer
I suggest you use Interaction Manager
As react-native is single threaded, JS gets blocked while running animation which can cause UI to lag and jitter.
Attaching code with changes
import 'react-native-gesture-handler';
import * as React from 'react';
import {
Text,
View,
StyleSheet,
Image,
InteractionManager,
} from 'react-native';
import Constants from 'expo-constants';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
const Drawer = createDrawerNavigator();
const Tab = createMaterialBottomTabNavigator();
const Home = (props) => {
React.useEffect(() => {
const interactionPromise = InteractionManager.runAfterInteractions(() =>
setShowContent(true)
);
return () => interactionPromise.cancel();
}, []);
const [showContent, setShowContent] = React.useState(false);
return showContent ? (
<View>
<Text>Home</Text>
<Image
source={{
uri: 'https://images.unsplash.com/photo-1596265371388-43edbaadab94?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80',
}}
style={{ height: 500, width: 500 }}
resizeMode={'cover'}></Image>
</View>
) : null;
};
const Activity = () => {
return <Text>Activity</Text>;
};
const BottomTab = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen
name="Activity"
component={Activity}
listeners={({ navigation, route }) => ({
focus: () => {
navigation.getParent().setOptions({
headerShown: false,
});
},
blur: () => {
navigation.getParent().setOptions({
headerShown: true,
});
},
})}
/>
</Tab.Navigator>
);
};
export default function App() {
return (
<View style={styles.container}>
<NavigationContainer>
<Drawer.Navigator screenOptions={{ headerMode: 'float' }}>
<Drawer.Screen
options={{ headerStyle: { height: 100 } }}
name="BottomTab"
component={BottomTab}
/>
</Drawer.Navigator>
</NavigationContainer>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});
i have this stack navigator:
const StackNavigator = () => (
<Stack.Navigator headerMode="screen" navigationOptions screenOptions={ss}>
<Stack.Screen name="Main" component={MainScreen} headerMode="screen" />...............
and i have object of screen options:
const ss = {
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
gestureEnabled: true,
gestureDirection: "horizontal",
headerTitleAlign: "center",
headerHideShadow: true,
headerTintColor: "red",
headerStyle: {
borderBottomWidth: 0.5,
borderColor: "white",
backgroundColor: "#1d2731",
},
headerTitleStyle: {
color: "white",
},
headerLeft: () => <AnimateHamburger navigation={navigation} />,
};
no when i get inside the component AnimatedHamburger
i dont get the props of openDrawer ...i get "...
navigation.openDrawer is not function....................
the AnimateHamburger component:
const AnimateHamburger = ({ navigation }) => {
console.log(navigation);
const isDrawerOpen = useIsDrawerOpen();
const toggleMenu = () => {
navigation.openDrawer();
};
return (
<View style={styles.icon}>
<Icon
style={styles.icon}
onPress={toggleMenu}
name={isDrawerOpen ? "enter" : "bars"}
type={isDrawerOpen ? "antdesign" : "font-awesome"}
color="black"
size={30}
/>
</View>
);
};
PLEASE help me how can i get the navigation props to toggle my drawer from the AnimateHamburger component
If you receiving openDrawer is not a function that's probably you are trying to access this method in a nested navigator which don't know about the parent drawer navigator. You can access drawer methods with DrawerAction from react-navigation take a look here:
https://reactnavigation.org/docs/drawer-actions
And use it like this:
https://reactnavigation.org/docs/nesting-navigators/#navigator-specific-methods-are-available-in-the-navigators-nested-inside
I have a drawer item "Share App" where I want to open an alert and display a message rather than opening an entire screen in react native. My code is as follows:
const Screen6_StackNavigator = createStackNavigator({
//All the screen from the Screen6 will be indexed here
Sixth: {
screen: ShareApp, //don't want this screen
title:'Share',
navigationOptions: ({ navigation }) => ({
headerLeft: () => <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#138808',
},
headerTintColor: '#fff',
}),
},
});
const DrawerNavigatorExample = createDrawerNavigator({
ShareApp: {
//Title
screen: Screen6_StackNavigator,
navigationOptions: {
drawerLabel: 'Share App',
drawerIcon: (<Entypo name="share" size={20} color='black'></Entypo>)
},
},
);
Where Do I add the onPress parameter in order to call the function? I dont want the screen parameter, want a function to be called only when I click on Share App.
How to do that in react native??
Do help as I am new in React native development....
Thanks.
You can create a custom drawer content component and pass it to the contentComponent option in the DrawerNavigatorConfig.
Creating the custom drawer content:
const CustomDrawerContentComponent = (props) => (
<ScrollView>
<SafeAreaView
style={{ flex: 1 }}
forceInset={{ top: 'always', horizontal: 'never' }}>
<TouchableOpacity
onPress={() => {
// Do something...
Alert.alert('Heading', 'Body');
}}
style={{ left: 15, flexDirection: 'row', alignItems: 'center' }}>
<Entypo name="share" size={20} color='black'></Entypo>
<Text style={{ marginLeft: 30, fontWeight: 'bold' }}>Share App</Text>
</TouchableOpacity>
<DrawerItems {...props} />
</SafeAreaView>
</ScrollView>
);
The DrawerItems component will render clickable drawer options based on the screens you create, but above the DrawerItems we can add your share button for example.
Passing the custom drawer content component to contentComponent
const DrawerNavigatorExample = createDrawerNavigator(
{
Screen1: {
// Properties...
},
// Other screens...
},
{
// Pass custom drawer content component...
contentComponent: props => <CustomDrawerContentComponent {...props} />,
// Other configurations...
},
);
DrawerItems should be imported from react-navigation-drawer.
I created a project using CRNA that uses React-Navigation. In one of the screen I have a background image that cover the entire screen and I want to including the header.
Like this image :
Should I just hide the header and use a View that contains the element that I want? If yes will this cause any trouble in case of deep linking?
Solution
React Navigation offers a cool props called headerTransparent that can be used in
order to render something under the header.
So the code at the should look like this :
static navigationOptions = {
headerTransparent: true
}
Right now with React Navigation 5 we can do something like this:
{
headerShown: true,
headerTransparent: true,
}
For example:
const Screen = ({ navigation }) => {
navigation.setOptions({
headerShown: true,
headerTransparent: true,
});
return (
<View>
<Text>Render your component</Text>
</View>
);
};
this worked for me :
navigationOptions: {
...
headerTransparent: true,
headerStyle: {
backgroundColor: 'transparent',
...
}
}
To achieve this effect you need to follow those steps:
Change the style of the navigation header with absolute position, transparent background and no border.
Use ImageBackground component as parent component for your screen with the image that you want to use as background.
Add padding top to this ImageBackground to fix the overlapping.
So your code should looks something similar to this:
import React, {Component} from 'react';
import {
StyleSheet,
Button,
ImageBackground,
Platform,
} from 'react-native';
import {
createStackNavigator,
} from 'react-navigation';
class HomeScreen extends Component {
render() {
return (
<ImageBackground
style={styles.container}
source={require('./images/bg.png')}
>
<Button
onPress={() => {}}
title="Just a button"
/>
</ImageBackground>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Platform.OS === 'ios' ? 60 : 80,
}
});
const App = createStackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: {
title: 'Home',
headerStyle: {
position: 'absolute',
backgroundColor: 'transparent',
zIndex: 100,
top: 0,
left: 0,
right: 0,
elevation: 0,
shadowOpacity: 0,
borderBottomWidth: 0,
}
},
}
})
export default App;
Solution:
navigationOptions: {
headerTransparent: {
position: 'absolute',
backgroundColor: 'transparent',
zIndex: 100,
top: 0,
left: 0,
right: 0
}
If using React Navigation 6.x, the option is the same headerTransparent:
<Stack.Screen
name="BottomTab"
component={BottomTabNavigator}
options={{
headerTransparent: true,
}}
/>
You need to use headerTransparent and headerShadowVisible otherwise if you just use headerTransparent a shadow will be left. This works with React Navigation 6.x. See de docs here https://reactnavigation.org/docs/native-stack-navigator/#headershadowvisible
<Stack.Screen name='Main' component={Main}
options={{
title: 'MainPage',
headerTransparent: true,
headerShadowVisible: false
}}
/>
I have achieved it setting the navigation options like this:
BirdDetails.navigationOptions = () => {
return {
...NavStyle,
headerStyle: {
backgroundColor: 'transparent',
},
headerTransparent: {
position: 'absolute',
},
headerLeft: <Back></Back>,
headerRight: <HeaderDetailsRight></HeaderDetailsRight>,
};
};
With V5
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: true,
headerTransparent:true
}}
>
<Stack.Screen name="Home" component={HomeScreen}/>
<Stack.Screen name="Detail" component={DetailScreen}/>
<Stack.Screen name="Setting" component={SettingScreen}/>
</Stack.Navigator>
</NavigationContainer>
this worked for me:
headerStyle: {elevation:0, backgroundColor:"transparent"}
set elevation to 0 so there is no shadow.
I did it this way, it has one flaw though, in the the background color must be hard-coded. This approach is specifically for ScrollView and starts out transparent becoming opaque (keeping the original text).
Since this was designed for native stack navigator to leverage iOS' large text the headerHeight also needs to be adjusted to the proper values.
const navigation = useNavigation();
return (
<ScrollView
onLayout={(e) => {
navigation.setOptions({
headerStyle: {
backgroundColor: "transparent",
},
});
}}
onScroll={(e) => {
const headerOpacity =
Math.min(
Math.max(e.nativeEvent.contentOffset.y, 0) / headerHeight,
1.0
) ?? 0.0;
navigation.setOptions({
headerStyle: {
elevation: headerOpacity,
backgroundColor: `rgba(255,0,0,${headerOpacity})`,
},
});
}}
scrollEventThrottle={16}
contentInsetAdjustmentBehavior="never"
>
How can I customize headerLeft TabNavigator of React Navigation.
Here's one of my screens :
I want to remove the Back from the headerLeft
Is it possible ?
Here's my code :
DetailTabs = TabNavigator({
DetailResult:{
screen:DetailResult,
navigationOptions:{
title:'Detail Penginapan',
headerTitleStyle:{
fontSize:14,
textAlign: "center",
flex: 1,
},
tabBarVisible: false,
headerStyle:{
backgroundColor:'#4A94FB',
borderBottomColor: 'transparent',
},
headerTintColor: 'white'
}
}
})
By default, HeaderBackButton component is used. You can implement it and use it to override the back button styles, press props, for example:
link to docs
import { HeaderBackButton } from '#react-navigation/stack';
//in newer versions use:
//import {HeaderBackButton} from '#react-navigation/elements';
const styles = StyleSheet.create({
custom: {
// Custom styles here
}
});
<Screen
name="Home"
component={HomeScreen}
options={{
headerLeft: (props) => (
<HeaderBackButton
{...props}
style={styles.custom}
onPress={() => {
// Do something
}}
/>
),
}}
/>;
If you want full control, you can use your custom back button component, example:
import { CustomBackButton } from 'path/to/custom/component';
<Screen
name="Home"
component={HomeScreen}
options={{
headerLeft: (props) => (
<CustomBackButton {...props} />
),
}}
/>;
You probably just need to set headerBackTitle to null. Check out the docs for headerLeft for more info.
Like this:
DetailTabs = TabNavigator({
DetailResult:{
screen:DetailResult,
navigationOptions:{
title:'Detail Penginapan',
headerTitleStyle:{
fontSize:14,
textAlign: "center",
flex: 1,
},
tabBarVisible: false,
headerStyle:{
backgroundColor:'#4A94FB',
borderBottomColor: 'transparent',
},
headerTintColor: 'white',
headerBackTitle: null,
}
}
})
Key is to put this code from where the back button is clicked, not in App.js
In sample below, for Icon to work, use import Icon from 'react-native-vector-icons/Feather';
constructor(props) {
super(props);
this.state = {
// what ever
};
this.props.navigation.setOptions({
headerLeft: () => (
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Home')}
>
<Icon style = {{paddingLeft : 10}} name="arrow-left" size={26} color="black" />
</TouchableOpacity>
),
});
}