visit
This tutorial is the fifth part of our React Native Car Parking App UI clone series. In the last part, we successfully implemented the Map Markers in MapView section. In this part of the tutorial series, we are going to continue from where we left off in the last part. So, it is recommended to go through all the previous parts of this tutorial series in order to get the full insight and development of the project.
Overview
In this fifth part of the tutorial series, we are going to implement the Header section. The Header section will include the detected location name along with a menu icon button on the right side. But first, the idea is to transfer all the color and size style properties to a completely different file and import it into our Map Screen. Then, we will style the size and color of components in the map screen using the properties from our external file. Lastly, we will implement the header section with the menu button which is quite easy.So, let us begin!!
In this step, we are going to store our size and color properties used very commonly on the map screen to a different file called ‘theme.js’. This will make things easier for us to assign styles to different components. Now, we need to create a file called
‘theme.js’
in our main project folder as shown in the code snippet below:As we can see, we have got the
‘theme.js’
file. Now, in the theme.js file we need to define our color and size properties as shown in the code snippet below:const COLORS = {
red: '#D83C54',
gray: '#7D818A',
black: '#3D4448',
white: '#FFFFFF',
overlay: '#C1BEC0',
};
const SIZES = {
base: 12,
icon: 16,
font: 16,
}
export {
COLORS,
SIZES,
}
Here, we have defined the color and size style properties in the
COLORS
and SIZES
constant variables that are then exported. The COLORS
variable contains different color properties containing their respective color codes. And for the SIZES
variable, we have defined base size as 12 and icon and font sizes to be 16 pixels.Since we have defined some common style properties in the
theme.js
file, here we are going to import the styles from theme.js
file and integrate them into our component inline styles as well as the styles in the StyleSheet
component. But first, we need to import the theme.js file into our Map.js file as shown in the code snippet below:import * as theme from '../theme';
Now, we are going to change the color and size style properties in accordance with the pre-defined styles from theme.js file.Changing color style properties in accordance with theme.js
Here, we are going to change the color style properties with the
COLORS
variable from the theme.js
file. All the changes made to the style properties in the StyleSheet
component is provided in the code snippet below: container: {
flex: 1,
backgroundColor: theme.COLORS.white
},
parking : {
flexDirection : 'row',
backgroundColor : theme.COLORS.white,
borderRadius : 6,
padding : 15,
marginHorizontal: 24,
width : width - ( 24 * 2 )
},
buy: {
flex: 1.25,
flexDirection : 'row',
padding : 8,
borderRadius : 6,
backgroundColor : theme.COLORS.red
},
marker: {
flexDirection: 'row',
backgroundColor: theme.COLORS.white,
borderRadius: 24,
paddingVertical: 12,
paddingHorizontal: 24,
borderWidth: 1,
borderColor: theme.COLORS.white,
},
markerPrice: {
color: theme.COLORS.red,
fontWeight: 'bold',
},
markerStatus: {
color: theme.COLORS.gray
},
shadow: {
shadowColor: theme.COLORS.black,
shadowOffset: {
width: 0,
height: 6,
},
shadowOpacity: 0.1,
shadowRadius: 4,
backgroundColor : theme.COLORS.white ,
elevation : 15
},
active: {
borderColor: theme.COLORS.red,
},
Now, we have some inline styles as well bound to the different components in renderParking() method. We need to change them in accordance with
COLORS
variable as well. All overall code with changes is provided in the code snippet below: <TouchableWithoutFeedback key={`parking-${item.id}`} onPress={() => this.setState({ active: item.id })} >
<View style={[styles.parking, styles.shadow]}>
<View style={{flex : 1, flexDirection : 'column'}}>
<Text style={{fontSize: 16}}>x {item.spots} {item.title}</Text>
<View style={{width : 100, borderRadius : 6, borderColor : theme.COLORS.gray, borderWidth : 0.7, padding : 4}}>
<Text style={{fontSize : 16}}>05:00 hrs</Text>
</View>
</View>
<View style={{flex : 1.5, flexDirection : 'row'}}>
<View style={{flex : 0.5, justifyContent: 'center', marginHorizontal : 24}}>
<View style={{flex: 1, flexDirection : 'row', justifyContent : 'space-between', alignItems : 'center'}}>
<Ionicons name='ios-pricetag' size={16} color={theme.COLORS.gray}/>
<Text>${item.price}</Text>
</View>
<View style={{flex: 1, flexDirection : 'row', justifyContent : 'space-between', alignItems : 'center'}}>
<Ionicons name='ios-star' size={16} color={theme.COLORS.gray}/>
<Text>{item.rating}</Text>
</View>
</View>
<TouchableOpacity style={styles.buy}>
<View style={{flex:1, justifyContent: 'center'}}>
<Text style={{fontSize : 25, color : theme.COLORS.white}}>${item.price *2}</Text>
<Text style={{ color : theme.COLORS.white}}>{item.price}x{hours[item.id]} hrs</Text>
</View>
<View style={{flex : 0.5, justifyContent : 'center', alignItems : 'center'}}>
<Text style={{fontSize: 25, color : theme.COLORS.white}}>></Text>
</View>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
Hence, we have completely changed the color properties. Now, we are going to do the same with size properties in accordance with
SIZES
variable from theme.js
file.Here, we are going to change the size style properties with the
SIZES
variable from the theme.js file. All the changes made to the style properties in the StyleSheet
component is provided in the code snippet below:const styles = StyleSheet.create({
parkings:{
position: 'absolute',
right: 0,
left: 0,
bottom: theme.SIZES.base * 2,
paddingBottom : theme.SIZES.base * 2
},
parking : {
flexDirection : 'row',
backgroundColor : theme.COLORS.white,
borderRadius : 6,
padding : 15,
marginHorizontal: theme.SIZES.base * 2,
width : width - ( theme.SIZES.base * 4)
},
marker: {
flexDirection: 'row',
backgroundColor: theme.COLORS.white,
borderRadius: theme.SIZES.base * 2,
paddingVertical: 12,
paddingHorizontal: theme.SIZES.base * 2,
borderWidth: 1,
borderColor: theme.COLORS.white,
},
});
Also, we have some inline size styles as well bound to the different components in renderParking() method. We need to change them in accordance with
SIZES
variable as well. All overall code with changes is provided in the code snippet below: <TouchableWithoutFeedback key={`parking-${item.id}`} onPress={() => this.setState({ active: item.id })} >
<View style={[styles.parking, styles.shadow]}>
<View style={{flex : 1, flexDirection : 'column'}}>
<Text style={theme.SIZES.font}>x {item.spots} {item.title}</Text>
<View style={{width : 100, borderRadius : 6, borderColor : theme.COLORS.gray, borderWidth : 0.7, padding : 4}}>
<Text style={theme.SIZES.font}>05:00 hrs</Text>
</View>
</View>
<View style={{flex : 1.5, flexDirection : 'row'}}>
<View style={{flex : 0.5, justifyContent: 'center', marginHorizontal : theme.SIZES.base * 2}}>
<View style={{flex: 1, flexDirection : 'row', justifyContent : 'space-between', alignItems : 'center'}}>
<Ionicons name='ios-pricetag' size={theme.SIZES.icon} color={theme.COLORS.gray}/>
<Text>${item.price}</Text>
</View>
<View style={{flex: 1, flexDirection : 'row', justifyContent : 'space-between', alignItems : 'center'}}>
<Ionicons name='ios-star' size={theme.SIZES.icon} color={theme.COLORS.gray}/>
<Text>{item.rating}</Text>
</View>
</View>
<TouchableOpacity style={styles.buy}>
<View style={{flex:1, justifyContent: 'center'}}>
<Text style={{fontSize : 25, color : theme.COLORS.white}}>${item.price *2}</Text>
<Text style={{ color : theme.COLORS.white}}>{item.price}x{hours[item.id]} hrs</Text>
</View>
<View style={{flex : 0.5, justifyContent : 'center', alignItems : 'center'}}>
<Text style={{fontSize: 25, color : theme.COLORS.white}}>></Text>
</View>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
Hence, we have completely changed the size properties based on the
SIZES
variable.Now, we are going to make the code in
Map.js
file more clearer and standard. For that, we are going to move some inline style properties to the StyleSheet
component.Here, we are going to make our code clearer by moving our inline styles in different components to the
StyleSheet
component. For that, we need to define a style variable for each inline styles. Here, in the Map.js
file, most of the inline styles are in the renderParking() method. So, first we are going to define the StyleSheet
variable for each inline styles as shown in the code snippet below:hours : {
flex : 1,
flexDirection : 'column'
},
hoursTitle: {
fontSize: theme.SIZES.text,
fontWeight: '500',
},
parkingInfoContainer : {
flex : 1.5,
flexDirection : 'row'
},
parkingInfo : {
flex : 0.5,
justifyContent: 'center',
marginHorizontal : theme.SIZES.base * 2
},
parkingIcon : {
flex: 1,
flexDirection : 'row',
justifyContent : 'space-between',
alignItems : 'center'
},
buyTotal : {
flex:1,
justifyContent: 'center'
},
buyButton : {
flex : 0.5,
justifyContent : 'center',
alignItems : 'center'
},
buyTotalPrice : {
fontSize : 25,
color : theme.COLORS.white
}
Now, we need to assign these
StyleSheet
properties variables to their respective component as shown in the code snippet below: <TouchableWithoutFeedback key={`parking-${item.id}`} onPress={() => this.setState({ active: item.id })} >
<View style={[styles.parking, styles.shadow]}>
<View style={styles.hours}>
<Text style={theme.SIZES.font}>x {item.spots} {item.title}</Text>
<View style={{width : 100, borderRadius : 6, borderColor : theme.COLORS.gray, borderWidth : 0.7, padding : 4}}>
<Text style={styles.hoursTitle}>05:00 hrs</Text>
</View>
</View>
<View style={styles.parkingInfoContainer}>
<View style={styles.parkingInfo}>
<View style={styles.parkingIcon}>
<Ionicons name='ios-pricetag' size={theme.SIZES.icon} color={theme.COLORS.gray}/>
<Text>${item.price}</Text>
</View>
<View style={styles.parkingIcon}>
<Ionicons name='ios-star' size={theme.SIZES.icon} color={theme.COLORS.gray}/>
<Text>{item.rating}</Text>
</View>
</View>
<TouchableOpacity style={styles.buy}>
<View style={styles.buyTotal}>
<Text style={styles.buyTotalPrice}>${item.price *2}</Text>
<Text style={{ color : theme.COLORS.white}}>{item.price}x{hours[item.id]} hrs</Text>
</View>
<View style={styles.buyButton}>
<Text style={{fontSize: 25, color : theme.COLORS.white}}>></Text>
</View>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
In this step, we are going to implement our
Header Section
in our Map.js file. The Header Section
will contain a detected location name as shown in the Map as well as a menu icon button on the right side. In our previous parts of this tutorial series, we have already separated a function called renderHeader() method. This renderHeader() method returns the template for the Header
section. We also have called this renderHeader() method in the render()
method of our Map.js file.Now, we are going to add some components to renderHeader() method which will implement the
Header Section
. For that, we need to use the code from the following code snippet:renderHeader(){
return(
<View style={styles.header}>
<View style={{ flex: 1, justifyContent: 'center' }}>
<Text style={styles.headerTitle}>Detected location</Text>
<Text style={styles.headerLocation}>San Francisco, US</Text>
</View>
</View>
)
}
Here, we have a parent
View
component that wraps a child View
component with some inline flex styles. This child View
component wraps two Text
components that will display the detected location name. The Text
components are also bound to some styles. The required styles are provided in the code snippet below: header: {
flexDirection: 'row',
justifyContent: 'center',
paddingHorizontal: theme.SIZES.base * 2,
paddingTop: theme.SIZES.base * 2.5,
paddingBottom: theme.SIZES.base * 1.5,
},
headerTitle: {
color: theme.COLORS.gray,
},
headerLocation: {
fontSize: theme.SIZES.font,
fontWeight: '500',
paddingVertical: theme.SIZES.base / 3,
},
Here, we are going to add a menu icon to the right side of the
Header Section
. For that, we are going to use the Ionicons component which we have already imported from the vector-icons package provided by expo client. The code to add the icon is provided in the code snippet below: <View style={styles.header}>
<View style={styles.headerLocationInfo }>
<Text style={styles.headerTitle}>Detected location</Text>
<Text style={styles.headerLocation}>San Francisco, US</Text>
</View>
<View style={styles.headerIcon }>
<TouchableWithoutFeedback>
<Ionicons name="ios-menu" size={theme.SIZES.icon * 1.5} />
</TouchableWithoutFeedback>
</View>
Here, we have added another child
View
component below the View
component wrapping text for the detected location. The second child
View
component with some inline flex styles wraps the TouchableWithoutFeedback
component. Then, the
TouchableWithoutFeedback
component wraps the Ionicons
component with the menu icon and size prop.The required styles are provided in the code snippet below: headerIcon :{
flex: 1,
justifyContent: 'center',
alignItems: 'flex-end',
},
headerLocationInfo : {
flex: 1,
justifyContent: 'center'
},