Problem with custom header in react navigation - javascript

I'm trying to make a custom header with react navigation but i can't get proper resoult. I want red view to cover all of the blue one but I can't figure it out.
Here is a picture
My HomeStack.js:
const screens = {
Home: {
screen: HomeScreen,
}
}
const options = {
defaultNavigationOptions: {
headerTitle: () => <Header/>,
headerStyle: {
backgroundColor: 'lightblue',
height: 60,
}
}
}
const HomeStack = createStackNavigator(screens, options)
const Navigator = createAppContainer(HomeStack)
export default Navigator
My Header.js:
class Header extends Component {
render() {
return(
<View style={style.conteiner}>
<Text style={style.text}>Text</Text>
</View>
)
}
}
const style = StyleSheet.create({
conteiner: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'red',
},
text: {
color: '#fff',
fontSize: 20,
}
})
export default Header

If I understand you correctly, then you want to define a custom component for the entire header. You are using your custom header component to set headerTitle:
const options = {
defaultNavigationOptions: {
headerTitle: () => <Header/>, <-- here
headerStyle: {
backgroundColor: 'lightblue',
height: 60,
}
This is what the documentation says about headerTitle:
Sometimes you need more control than just changing the text and styles
of your title -- for example, you may want to render an image in place
of the title, or make the title into a button. In these cases you can
completely override the component used for the title and provide your
own.
This option is only intended for replacing the title component, not the entire header. Unless you have some very specific requirements, you can likely achieve what you are looking for using a combination of headerStyle, headerTintColor and headerTitle.

You need to pass your custom header component to the header props for the stack navigator.
headerTitle is for the title inside the header component.
https://reactnavigation.org/docs/4.x/stack-navigator#header
https://reactnavigation.org/docs/4.x/stack-navigator#headertitle
https://reactnavigation.org/docs/4.x/stack-navigator

Related

Using variables inside react native stylesheets wont recognize the variable

I import a color as props.color into my functional component and set it as the state 'tagColor'. When I use tagColor as a value in my stylesheet to set the background color i receive the error 'variable tagColor not found'
How can I use variables inside my stylesheet?
const Tag = (props) => {
const [tagColor, setColor] = useState(props.color)
return (
<View style={styles.container}>
<TouchableOpacity style={styles.tag} title='tag'>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: {
alignItems: "center",
justifyContent: "center",
height: 25,
display: 'flex'
},
tag: {
backgroundColor: tagColor,
}
});
export default Tag;
Well, of course it doesn't recognize tagColor, it's in a different scope. Notice tagColor is in the scope of your function component, while the StyleSheet is a different scope.
One way to solve this is to directly pass the backgroundColor to the style prop, like that:
<TouchableOpacity style={{backgroundColor: tagColor}} title="tag">
Another way is to define the tag class in your StyleSheet as a function that receives the color and returns the style, like:
const styles = StyleSheet.create({
container: {
...
},
tag: tagColor => ({
backgroundColor: tagColor,
})
});
And then use it like that:
<TouchableOpacity style={styles.tag(tagColor)} title="tag">
I'd go with the first way if you don't have any more styles other than backgroundColor. If you need more styles, go with the 2nd method.

How to Default export react withRouter while using material UI makeStyles

I am using Material UI makeStyles with class components and adding use style as props while default exporting it in an arrow function.
export default () => {
const classes = useStyles();
return (
<LoginClass classes={classes} />
)
}
In react documentation it states that you need to use hooks while using makestyles which currently until now I have been doing correctly.
The issue I am facing now is I want to use react withRouter to use:
this.props.history.push
which I dont have access to in my class.
Below is my code that works perfectly but I cant direct users to other pages.
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: '#009688',
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
backgroundColor: '#33ab9f',
'&:hover': {
backgroundColor: '#009688',
},
},
}));
class LoginClass extends React.Component {
handleSubmit(event) {
this.props.history.push('/home') //dont have access to history unless I use withRouter
}
render() {
const classes = this.props.classes;
const { input } = this.state
return (
<React.Fragment>
<CssBaseline />
<MenuBarClass classes={classes} isLogin={this.state.isLogin} />
</React.Fragment>
)
}
}
After alot of research I have found a way to direct users to other pages by using:
export default withRouter(withStyles(useStyles)(LoginClass))
but using the above export distorts my whole page design.
any solution with using classes and makeStyles would be greatly appreciated.
Thank you.
so I can direct the users to other pages.
Try this way:
const styles = theme => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: '#009688',
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
backgroundColor: '#33ab9f',
'&:hover': {
backgroundColor: '#009688',
},
},
});
...
export default withRouter(withStyles(styles)(LoginClass))

Custom Header don't take full space in stack bar

So i made a custom header component and tried to put it in the stack bar title, but the view doesn't take the full space even when passing the width and height to 100%.i also tried flex :1 but that doesn't work also
// header.js
import React from 'react';
import {View,Text,Button,StyleSheet} from 'react-native'
//class Header extends React.Component {
//render(){
export default function Header(){
return (
<View style={styles.header}>
<View>
<Text style={styles.text}>MEDICLIC</Text>
</View>
</View>
)
}
const styles = StyleSheet.create({
header: {
width:'100%',
height:'100%',
flexDirection:'row',
alignItems:'center',
justifyContent:'center',
backgroundColor:'#3498db',
},
text:{
fontWeight: '600',
color:'#ecf0f1',
fontSize: 32,
}
});
//export default Header
this is my app.js code where i used also a drawer navigation,
// APP.js
import React from 'react';
import Header from './Components/Header'
import { createDrawerNavigator } from 'react-navigation-drawer'
import {createAppContainer } from 'react-navigation'
import {createStackNavigator } from 'react-navigation-stack'
import ConnectionScreen from './Screens/ConnectionScreen';
import AccueilScreen from './Screens/AccueilScreen';
import AboutScreen from './Screens/AboutScreen';
export default class App extends React.Component {
render(){
return (
<AppNavigator/>
);
}
}
const AppDrawerNavigator = createDrawerNavigator({
Accueil:{
screen: AccueilScreen
},
SeConnecter: {
screen:ConnectionScreen} ,
Apropos : {
screen: AboutScreen
},
});
const screens = {
Accueil:{
screen : AppDrawerNavigator
},
SeConnecter: {
screen:AppDrawerNavigator
} ,
Apropos : {
screen: AppDrawerNavigator
},
}
const AppStackNavigator = createStackNavigator(screens,{
defaultNavigationOptions:{
headerTitle: () => <Header/>,
headerTintColor :'#fff',
headerStyle :{
backgroundColor:'#fff',
height: 100,
},
}
});
const AppNavigator= createAppContainer(AppStackNavigator);
What i see on my android device
enter image description here
<View style={{ flexDirection: "row", justifyContent: 'center' ,backgroundColor: 'red' ,width:360 }}>
///... 3 views and text in them
</View>
I did this, hard coded the width to main view of component using in place of title. about width 360 takes complete width having equal width on both left and right end.
Please do mention if you find a better way to sort the things. Thanks in advance.
I came across this problem today also, but after searching for solution for more than a hour, I finally get a way around it. The problem was that react native doesn't allow full access on the way the header component works anymore, you can only put the component that you want, but not override the header.
Therefore, to configure the stack header to your preference, you have to configure the header from the stack headerStyle property from the options prop.
For mine, I configure the background from the stack headerStyle property so as to fill the whole header,
import { createStackNavigator } from "#react-navigation/stack";
import Home from "../screens/home";
import ReviewDetails from "../screens/reviewDetails";
import Header from "../shared/header";
const Stack = createStackNavigator();
export default function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
options={{
headerTitle: () => <Header />,
headerStyle: {
backgroundColor: "coral",
},
}}
/>
<Stack.Screen name="ReviewDetails" component={ReviewDetails} />
</Stack.Navigator>
);
}
Then I use the absolute position on the header component style to put it in the middle accordingly.
Note: percent are still not working for the absolute positioning, so you still have to use pixels.
import { StyleSheet, Text, View } from "react-native";
import { MaterialIcons } from "#expo/vector-icons";
const Header = () => {
return (
<View style={styles.cont}>
<MaterialIcons name="menu" size={30} />
<View>
<Text style={styles.text}>GameZone</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
cont: {
flex: 1,
position: "absolute",
left: 80,
flexDirection: "row",
justifyContent: "space-around",
alignItems: "center",
},
text: {
fontSize: 24,
fontFamily: "nunito-bold",
letterSpacing: 2,
},
});
export default Header;
Here is the preview from android mobile
preview of the code

React Native - Animate width shrink

In the header of my React Native app, I have a conditional icon and a Searchbar.
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
headerTitle: (
<View
style={{
flex: 1,
backgroundColor: Platform.OS === 'ios' ? '#e54b4d' : '',
alignItems: 'center',
flexDirection: 'row',
paddingHorizontal: 10,
height: StatusBar.currentHeight,
}}>
{params.isIconTriggered && <Icon name="chevron-left" size={28} />}
<SearchBar
round
platform={'default'}
placeholder="Search"
containerStyle={{
flex: 1,
backgroundColor: 'transparent',
}}
/>
</View>
),
headerStyle: {
backgroundColor: '#e54b4d',
},
};
};
Normally the Searchbar will take the full width of the header which is what I want. If the condition isIconTriggered is true, an icon will appear in front of the Searchbar and the width of the SearchBar will shrink enough so that the icon is visible next to it.
However, there is no transition or animation when this happens and it does not feel nor look nice. I would like to add an animation to the Searchbar so the width shrinks gradually and smoothly when the condition is triggered and the icon appears.
Is that possible to achieve and how can I achieve this?
Try to learn Animated API of react native.
Here is how i done it with button trigger.
import React, {Component} from 'react';
import {StyleSheet, View, TextInput , Button, SafeAreaView, Animated} from 'react-native';
import FA from 'react-native-vector-icons/FontAwesome5'
const AnimatedIcon = Animated.createAnimatedComponent(FA)
// make your icon animatable using createAnimatedComponent method
export default class Application extends Component {
animVal = new Animated.Value(0);
// initialize animated value to use for animation, whereas initial value is zero
interpolateIcon = this.animVal.interpolate({inputRange:[0,1], outputRange:[0,1]})
interpolateBar = this.animVal.interpolate({inputRange:[0,1],outputRange:['100%','90%']})
// initialize interpolation to control the output value that will be passed on styles
// since we will animate both search bar and icon. we need to initialize both
// on icon we will animate the scale whereas outputRange starts at 0 end in 1
// on search bar we will animate width. whereas outputRange starts at 100% end in 90%
animatedTransition = Animated.spring(this.animVal,{toValue:1})
// we use spring to make the animation bouncy . and it will animate to Value 1
clickAnimate = () => {
this.animatedTransition.start()
}
// button trigger for animation
//Components that will use on Animation must be Animated eg. Animted.View
render() {
return (
<SafeAreaView>
<View style={styles.container}>
<View style={styles.search}>
{/* our icon */}
<Animated.View style={{width: this.interpolateBar}}>
<TextInput placeholder='search here' style={styles.input}/>
</Animated.View>
<AnimatedIcon name='search' size={28} style={{paddingLeft: 10,paddingRight:10, transform:[{scale: this.interpolateIcon}]}}/>
</View>
<Button title='animate icon' onPress={this.clickAnimate}/>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor:'#F79D42',
// flex: 1,
height:'100%',
paddingTop:20,
flexDirection: 'column',
// justifyContent: 'center',
alignItems:'center'
},
input:{
width: '100%',
height:40,
backgroundColor:'gray',
textAlign:'center'
},
search:{
flexDirection:'row-reverse',
width:'90%',
height:40,
alignItems:'center'
}
});
Solution using react-native-elements SearchBar component.
Wrapped the SearchBar Component inside Animated.View.
to explicitly animate the search bar
Like This:
<Animated.View style={{width: this.interpolateBar}}>
<SearchBar
placeholder="Type Here..."
containerStyle={{width: '100%'}}
/>
</Animated.View>
You can achieve this using Animated API of React Native.
You can check this tutorial for an overview of changing the size of elements with animation.
React-Native-Animatable is super cool!
Try this one out:
Create A custom animation object
import * as Animatable from 'react-native-animatable';
Animatable.initializeRegistryWithDefinitions({
const myAnimation = {
from: {
width: 200
},
to: {
width: 100
}
}
})
Use is as Animation value within a view or as a reference within a function call.
Within a view:
<Animatable.View useNativeDriver animation={myAnimation}/>
As a reference variable:
<Animatable.View useNativeDriver ref={ref=>(this.testAnimation = ref)}/>
Method:
testMethod = () => {
this.testAnimation.myAnimation();
}

React Navigation switching background colors and styling StackNavigator

I'm fairly new to React Native, but I have a simple working app with three scenes. I was previously using Navigator but it felt laggy and was excited to try out React Navigation (as in https://reactnavigation.org/). After implementing React Navigation, my background color switched from white to grey, and what was grey to white. This is a strange and shouldn't be related. However I didn't change my styles. I only implemented the new navigation and the colors changed. When I revert back to Navigator my colors return. I'm using StackNavigator. Has anyone else encountered this strange phenomenon?
Or maybe a better question is : how do I style my header and background color in React Navigation's StackNavigator?
To style the header in React Navigation use a header object inside the navigationOptions object:
static navigationOptions = {
header: {
titleStyle: {
/* this only styles the title/text (font, color etc.) */
},
style: {
/* this will style the header, but does NOT change the text */
},
tintColor: {
/* this will color your back and forward arrows or left and right icons */
}
}
}
For styling the backgroundColor, you just need to set the backgroundColor in your app otherwise you'll get the default color.
UPDATE!! As of May 2017 beta9 the navigationOptions are now flat
You can read about the breaking change here
You need to remove the object keys from the header object. Also, notice they have been renamed.
static navigationOptions = {
title: 'some string title',
headerTitleStyle: {
/* */
},
headerStyle: {
/* */
},
headerTintColor: {
/* */
},
}
Here is an example of what I am using to change the card background color and Header background and font color.
/*
1. Change React Navigation background color.
- change the style backgroundColor property in the StackNavigator component
- also add a cardStyle object to the Visual options config specifying a background color
*/
//your new background color
let myNewBackgroundColor = 'teal';
const AppNavigator = StackNavigator({
SomeLoginScreen: {
screen: SomeLoginScreen
}
}, {
headerMode: 'screen',
cardStyle: {backgroundColor: myNewBackgroundColor
}
});
//add the new color to the style property
class App extends React.Component {
render() {
return (
<AppNavigator style = {{backgroundColor: myNewBackgroundColor}} ref={nav => {this.navigator = nav;}}/>
);
}
}
/*
2. Change React Navigation Header background color and text color.
- change the StackNavigator navigationOptions
*/
/*
its not clear in the docs but the tintColor
changes the color of the text title in the
header while a new style object changes the
background color.
*/
//your new text color
let myNewTextColor = 'forestgreen';
//your new header background color
let myNewHeaderBackgroundColor = 'pink';
const AppNavigator = StackNavigator({
SomeLoginScreen: {
screen: SomeLoginScreen,
navigationOptions: {
title: 'Register',
header: {
tintColor: myNewTextColor,
style: {
backgroundColor: myNewHeaderBackgroundColor
}
},
}
}
}, {
headerMode: 'screen',
cardStyle:{backgroundColor:'red'
}
});
Use below code to create custom navigation header
static navigationOptions = {
title: 'Home',
headerTintColor: '#ffffff',
headerStyle: {
backgroundColor: '#2F95D6',
borderBottomColor: '#ffffff',
borderBottomWidth: 3,
},
headerTitleStyle: {
fontSize: 18,
},
};
Try this code.
static navigationOptions = {
title: 'KindleJoy - Kids Learning Center',
headerTintColor: '#ffffff',
/*headerBackground: (
<Image
style={StyleSheet.absoluteFill}
source={require('./imgs/yr_logo.png')}
/>
),*/
headerStyle: {
backgroundColor: '#1d7110',
borderBottomColor: 'black',
borderBottomWidth: 0,
},
headerTitleStyle: {
fontSize: 18,
}
};
I think none of the above answers worked for me in react-navigation 5 so, I made it mine own solution and share it with you
Just changed background of your theme in react-navigation 5 and you are good to go.
import React from 'react';
import { NavigationContainer, DefaultTheme } from '#react-navigation/native';
const MainNavigator = () => {
const MyTheme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
background: '#FFF',
},
};
return (
<NavigationContainer theme={MyTheme}>
...
</NavigationContainer>
);
};
export default MainNavigator;
https://reactnavigation.org/docs/themes/
Ok nothing worked for me, so I managed to figure out my own solution
static navigationOptions = ({ navigation, screenProps }) => ({
headerLeft: (
<NavBackButton onPress={() => { navigation.goBack(); }} />
),headerStyle: {
backgroundColor: CLColors.MAIN_BLUE
},
headerTitle: <Text style={[CLStyles.H6MEDIUM_WHITE, {marginLeft:8}]}>Profile</Text>
, footer: null,
});
headerTitle will do the magic to place a custom Text element here.
headerStyle will do the magic to change the background color of your navbar.
headerLeft will help you to customize your back button.
In stack navigator you can change it with contentStyle.backgroundColor like below syntax
<Stack.Navigator screenOptions={{ contentStyle: {backgroundColor: '#f6f6f6f'}}}>
note: #f6f6f6f is colour code of red colour you can change it as per your requirement, below is extra code snippets in case
const Stack = createNativeStackNavigator();
export default function App() {
return (
<>
<StatusBar style='auto' />
<NavigationContainer>
<Stack.Navigator screenOptions={{ contentStyle: {backgroundColor: '#f6f6f6f'}}}>
<Stack.Screen name="List Page" component={ListPage} />
<Stack.Screen name="List Page 2" component={ListPage} />
</Stack.Navigator>
</NavigationContainer>
</>
);
}

Categories

Resources