React Native Car Parking Finder App UI Clone #5: Build header

Krissanawat Kaewsanmuang
Nov 1 · 10 min read

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.

In case anyone wants to learn from the beginning, all the parts for this tutorial series are available below:

As stated in the previous parts, this tutorial series was inspired by the React native Store Locator template that provides us with a dynamic, fully-coded starter kit written in React Native that anyone can use to build their own store locator React Native application or initiate their own startup. And, this fifth part is also the continuation of coding implementations and designs from the YouTube video tutorial by React UI Kit for the Car parking Finder App UI clone. The video tutorial delivers the overall implementations using a fast coding style which may be difficult to grasp for any developer especially the beginners. However, this tutorial gives stepwise guidance on the implementation of each UI section. Hence, the readers can relax and take time to learn and implement the UI.

Overview

So, let us begin!!

Storing Style Properties in Different File

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.

Integrating Color style properties based on theme.js file

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

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.

Changing size properties in accordance with theme.js

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.

Organizing Inline styles to StyleSheet

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>

Hence, after everything is organized, we will get the same result as before which is shown in the following emulator screenshot:

As we can see, the result is the same as before with all the codes organized.

Implementing Header Section

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,
},

Hence, we will get the following result in our emulator screen:

Therefore, we have got the Detected Location name with proper style in the Header section.

Now, we need to add a menu icon button to the right side of the Header section.

Adding Menu Icon

<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'
},

Hence, we will get the following result in the emulator screen:

As we can see, we have the header section with the detected location name and the menu icon to the right.

Finally, we have successfully implemented the Header section in our map screen. With this, we have come to the end of this part of our tutorial. This completes our Map screen UI.

Conclusion

In the next part of this tutorial series, we are going to implement a Modal representing the parking spot cards.


Originally published at https://kriss.io on November 1, 2019.

React Native Mastery

Share thought on React Native

Krissanawat Kaewsanmuang

Written by

React native passionate developer, Coffee addict https://kriss.io

React Native Mastery

Share thought on React Native

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade