visit
This tutorial is the fourth part of our React Native Car Parking App UI clone series. In the last part, we successfully implemented the car parking spots 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 the previous parts of this tutorial series in order to get the full insight and development of the project.
As mentioned in the previous parts, the inspiration of this tutorial came from the React Native App Templates that provides us with an amazing, 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 fourth part is also the continuation of coding implementations and designs from the YouTube video tutorial by for the Camping Spots Finder App clone. The video tutorial uses a fast coding style to deliver the overall tutorial to the viewers which may be difficult to grasp for any developer especially the beginners. This tutorial gives step by step guidance on the implementation of each UI section. Hence, the readers can relax and take time to implement the UI.Overview
In this fourth part of the tutorial series, we are going to add the custom Map Marker which will represent the car parking spot locations on the map. The idea is to integrate the Marker component provided by MapView component into the MapView in order to show the default location markers. Then, we are going to customize the markers in order to make it as in the actual app. Lastly, we are going to add the active style to each map marker.So, let us begin!!
Firstly, we are going to make an extra change to our
ScrollView
in renderParkings() method. Here, we are going to change the ScrollView
into FlatList
in order to change our parking spot cards in the parking section into the list. By changing it into FlatList
, we will get all the advantages offered by FlatList
component as well as can include the ScrollView
props into the FlatList
component. The coding implementation for this is provided in the code snippet below:renderParkings(){
return(
<FlatList
horizontal
pagingEnabled
scrollEnabled
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
snapToAlignment="center"
style={styles.parkings}
data={parkingsSpots}
keyExtractor={(item, index) => `${item.id}`}
renderItem={({ item }) => this.renderParking(item)}
/>
)
}
Here, we have replaced the
ScrollView
with FlatList
component. Most of the required props that we integrated to the ScrollView
for a smooth swiping transition are also incorporated in the FlatList
component. The extra props that we have added are the data for the parkingsSpots, keyExtractor in order to identify each item in the list uniquely and renderItem which will return the template. FlatList
loops through each element of our parkingsSpots array and return the list view which can be customized as a template in the renderItem prop.Note that, we should not forget to import the FlatList component from the react-native package.
Now, we are also going to add react hook called componentWillMount(), which will change the state of our hours state to 1 as shown in the code snippet below:
componentWillMount() {
const hours = {};
parkingsSpots.map(parking => {hours[parking.id] = 1});
this.setState({ hours });
}
Now, we should get the same result as we did before with
ScrollView
. Hence, if we re-run the emulator, we will get the following result in our emulator screen:Here, we are going to add the Map Marker to our
MapView
component. For this, we will need to add some additional coordinate data to our parkingsSpots array data as provided in the code snippet below:const parkingsSpots = [
{
id: 1,
title: 'Parking 1',
price: 5,
rating: 4.2,
spots: 20,
free: 10,
coordinate: {
latitude: 37.78735,
longitude: -122.4334,
}
},
{
id: 2,
title: 'Parking 2',
price: 7,
rating: 3.8,
spots: 25,
free: 20,
coordinate: {
latitude: 37.78845,
longitude: -122.4344,
}
},
{
id: 3,
title: 'Parking 3',
price: 10,
rating: 4.9,
spots: 50,
free: 25,
coordinate: {
latitude: 37.78615,
longitude: -122.4314,
}
},
];
Now, we are going to add the Marker component to
MapView
component. For that, we need to define the Marker component which can be imported from MapView
component as shown in the code snippet below:const {Marker} = MapView;
The
MapView
component imported from the react-native-maps package also provides the Marker module. This Marker module enables us to add different location markers to the screen.Now, we are going to use the Marker component inside for
MapView
component. Since we have 3 parking spots data in order parkingsSpots array, we need to use map() array function to iterate through all the items. Then, the map() array function will return the Marker
component as shown in the code snippet below:render(){
return (
<View style={styles.container}>
{this.renderHeader()}
<MapView style={styles.map}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
>
{parkingsSpots.map(parking =>
<Marker
key={`marker-${parking.id}`}
coordinate={parking.coordinate}/>
)}
</MapView>
{this.renderParkings()}
</View>
);
}
}
Here, the
Marker
component has two props. One prop is key which identifies each marker uniquely. The other is coordinate prop which will take the latitude and longitude value to display the location marker on the screen.Hence, we will get the following result in the emulator screen:Here, we are going to make some customization to the map marker icon. We are going to add our own components and styles in order to make the marker icon appear as in the actual app. For that, we need to use the code from the following code snippet in the
Marker
component: {parkingsSpots.map(parking =>
<Marker
key={`marker-${parking.id}`}
coordinate={parking.coordinate}>
<View style={styles.marker}>
<Text>${parking.price}</Text>
<Text>({parking.free}/{parking.spots})</Text>
</View>
</Marker>
)}
Here, we have added a
View
component inside the Marker
component. The View
component wraps two Text
components having the price, free parking spots and total parking spots value. There are some styles used as well, which is provided in the code snippet below:marker : {
backgroundColor : 'white',
}
Adding styles
Here, we are going to add some extra styles to the components of the marker icon template. We are going to add styles to the
View
component and the Text
components that we added earlier as shown in the code snippet below:<Marker
key={`marker-${parking.id}`}
coordinate={parking.coordinate}>
<View style={[
styles.marker,
styles.shadow,
]}>
<Text style={styles.markerPrice}>${parking.price}</Text>
<Text style={styles.markerStatus}> ({parking.free}/{parking.spots})</Text>
</View>
</Marker>
marker: {
flexDirection: 'row',
backgroundColor: '#FFFFFF',
borderRadius: 24,
paddingVertical: 12,
paddingHorizontal: 24,
borderWidth: 1,
borderColor: '#FFFFFF',
},
markerPrice: {
color: '#D83C54',
fontWeight: 'bold',
},
markerStatus: {
color: '#7D818A'
},
shadow: {
shadowColor: "#3D4448",
shadowOffset: {
width: 0,
height: 6,
},
shadowOpacity: 0.1,
shadowRadius: 4,
backgroundColor : 'white',
elevation : 5
},
Note that, we have added a shadow style property here. If we run this application on iOS emulator then the shadow style properties will execute properly. But since we are using the android emulator, we will have to use the elevation style property for the shadow. But this elevation style property for implementing shadow in the Android platform does not seem to work in the expo. This may be due to the version problem. So, if adding the shadow style is mandatory then, it is recommended to use the external packages like react-native-shadow. Here, we are not going to use it as the shadow style is not mandatory.
Therefore, we will get the following result in the emulator screen:state = {
hours: {},
active : null
}
import {
StyleSheet,
Text, View,
ScrollView,
Dimensions,
TouchableOpacity,
FlatList,
TouchableWithoutFeedback
} from 'react-native';
For that, we are going to add a
TouchableWithoutFeedback
component wrapping the entire template in the renderParking() method. Then, we are going to add the key prop to TouchableWithoutFeedback
component instead of the inner View
component. Now, to change the active state we are going to use the setState function in the onPress event of the TouchableWithoutFeedback
component. The setState function will set the active state variable to parking spot ID on the basis of which one is clicked. The overall coding implementation is provided in the code snippet below:renderParking(item){
const { hours } = this.state;
return(
<TouchableWithoutFeedback key={`parking-${item.id}`} onPress={() => this.setState({ active: item.id })} >
<View style={[styles.parking, styles.shadow]}>
.....
</View>
</TouchableWithoutFeedback>
)
}
active: {
borderColor: '#D83C54',
},
Now, in the
Marker
component, we have a View
component with style properties. Now, we are going bind another style property to it based on the active state as shown in the code snippet below: <Marker
key={`marker-${parking.id}`}
coordinate={parking.coordinate}>
<TouchableWithoutFeedback onPress={() => this.setState({ active: parking.id })} >
<View style={[
styles.marker,
styles.shadow,
this.state.active === parking.id ? styles.active : null
]}>
<Text style={styles.markerPrice}>${parking.price}</Text>
<Text style={styles.markerStatus}> ({parking.free}/{parking.spots})</Text>
</View>
</TouchableWithoutFeedback>
</Marker>
Here, if the active state is equal to the parking ID value then the style we defined before will appear. Else, the style will be null. Here, we have also wrapped the entire marker icon template inside
Marker
component with the TouchableWithoutFeedback
component. This will perform the same function as in the TouchableWithoutFeedback
component in renderParking() method. The only difference is that the active style is triggered when we press on any map markers.There is also a small change made in the style property which is provided in the code snippet below:parkings :{
position: 'absolute',
right: 0,
left: 0,
bottom: 24,
paddingBottom : 24
},
Finally, we have successfully implemented the map markers in the
MapView
component of the map screen with active style as well. With this, we have come to the end of this part of our tutorial series. Most of the UI sections in the map screen is complete now.This tutorial is the fourth part of the React Native Car Parking Finder App UI clone tutorial series. In this part, we continued from where we left off in the third part of this tutorial series. In this part of the tutorial, we learned how to replace the
ScrollView
and make use of FlatList
with the same props. Then, we got step by step guidance on adding custom map markers to the map. Lastly, we also learned to configure the active style to map markers whenever the parking spot card or marker is pressed.In the next part of this tutorial series, we are going to configure inline styles in the
Stylesheet
component as well as implement the Header section.