Camping Spots Finder App UI Clone with React Native # 2: List Section
absek
Posted on October 12, 2019
This tutorial is the second part of our Camping Spots Finder App UI clone using React Native. In the previous part, we successfully implemented the Map view section along with the custom header and header tabs. This tutorial is the continuation of the same tutorial from where we left off in the last part. So, it is suggested to go through the previous parts for better understanding and insight into the overall project.
As stated in the previous part, this inspiration for this tutorial series came from React native real estate template that enables us to build fully functional ready to deploy mobile applications that anyone can use to build their own React Native applications. And, this second part is also the continuation of coding implementations and designs from the Youtube video tutorial by React UI Kit for the Camping Spots Finder App clone.
In this second part of this tutorial series, we are going to implement the list section that we separated in the previous part of this tutorial as well as set up the navigation to the settings screen. But first, we are going to make some simple changes to the header section in order to make it look clean and proper. Then, we are going to start implementing the list section and finally add the navigation at the end.
So, let us begin!!
Simple changes to Header Section
First and foremost, we are going to make some simple changes to the header section that includes the custom header and the header tabs. Here, in the Camping.js file render()
method, we are only going to include the renderMap()
and renderList()
method to the ScrollView component. Then, we are going to change the parent View
component to SafeAreaView
component and bind the style to it. After that, we are going to include the renderHeader()
method above the ScrollView
component as shown in the code snippet below:
render(){
return (
<SafeAreaView style={styles.container}>
{this.renderHeader()}
<ScrollView style={styles.container}>
{this.renderMap()}
{this.renderList()}
</ScrollView>
</SafeAreaView>
);
}
Note that: we need to import the SafeAreaView
component as well from the react-native package.
Here, we added the SafeAreaView as a parent component because it enables us to render content within the safe area boundaries of a device. However, we need to be careful that this feature only works with the iOS platform. So, we will have to add some extra style in the Android platform in order to achieve the same output as that of SafeAreaView.
But first, we are going to wrap the entire template of renderHeader()
method with another parent View
component and bind it with extra style. And then, we are going to call the renderTabs()
method inside this parent View
component after the View
component for custom header section as shown in the code snippet below:
renderHeader() {
return (
<View style={styles.headerContainer}>
<View style={styles.header}>
<View style={{flex: 2, flexDirection: 'row'}}>
<View style={styles.settings}>
<View style={styles.location}>
<FontAwesome name="location-arrow" size={14} color="white" />
</View>
</View>
<View style={styles.options}>
<Text style={{ fontSize: 12, color: '#A5A5A5', marginBottom: 5, }}>
Detected Location
</Text>
<Text style={{ fontSize: 14, fontWeight: '300', }}>
Northern Islands
</Text>
</View>
</View>
<View style={styles.settings}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('Settings')}>
<Ionicons name="ios-settings" size={24} color="black" />
</TouchableOpacity>
</View>
</View>
{this.renderTabs()}
</View>
)
}
Now, we need to add the style headerContainer
to the Stylesheet component. And the style with its properties is provided below:
headerContainer: {
top: 0,
marginTop : 20, //marginTop only in Android platform as SafeAreaView component doesnot work in it
height: height * 0.15,
width: width,
}
Here, we need to remember to add the marginTop
style property if we are developing for the Android platform. This is because the SafeAreaView
component doesn’t work.
Hence, we get the following result in our emulator screen:
As we can see, we have the header section with custom header and header tabs in the proper position.
Now, we are going to implement the list section in the renderList()
method that we defined in the previous tutorial part.
Implementing List Section
In this step, we are going to implement the list section in which there will be different camping spots image and description.
Including Mock Data
First, we are going to include the mock data for camping spots in an array inside the renderList()
method. The mock data is provided in the code snippet below:
const campings = [
{
id: 1,
type: 'rv',
name: 'Camping Paradise',
description: 'Popular spot for trekkers.',
rating: 4.9,
distance: 2.9,
price: 'Free',
image: 'https://images.unsplash.com/photo-1525811902-f2342640856e?fit=crop&w=900&h=600&q=130',
},
{
id: 2,
type: 'tent',
name: 'Lake Florida',
description: 'This is for all sunset lovers.',
rating: 4.9,
distance: 2.9,
price: 'Free',
image: 'https://images.unsplash.com/photo-1506535995048-638aa1b62b77?fit=crop&w=900&h=600&q=130',
},
];
Here, we have defined the mock data as campings
array which includes objects with camping spots detail. Now, we will move on to implementing the template for the list section.
Creating Template Item for List section
Here, we are going to start by implementing a simple template inside the renderList()
method. The template will contain some View
and Text
components with manually entered mock data as shown in the code snippet below:
<View>
<View>
<Text>Image</Text>
</View>
<View>
<Text>Camping title</Text>
<Text>Camping description</Text>
<View>
<Text>4.9</Text>
<Text>2.9 miles</Text>
<Text>Free</Text>
</View>
</View>
<View>
</View>
</View>
Hence, we will get the following result in our emulator screen:
As we can see, there are no styles and configurations added to it. We are going to do that in the next step.
Adding proper styles and icons
As the template we created above did not contain any styles, we are going to add some styles to it. Then, we are going to add some icons as well from the Ionicons
and FontAwesome
icon packages that we imported in the previous tutorial. We need to add several flex
style properties as well as add more View
components with styles to give the list item template a proper look. The code to implement the proper list item template is provided in the code snippet below:
<View style={styles.camping}>
<View>
<Image />
</View>
<View style={styles.campingDetails}>
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center' }}>
<Text style={{ fontSize: 14, fontWeight: 'bold' }}>
Camping title
</Text>
<Text style={{ fontSize: 12, color: '#A5A5A5', paddingTop: 5 }}>
Camping description
</Text>
</View>
<View style={{ flex: 1, flexDirection: 'row', }}>
<View style={styles.campingInfo}>
<FontAwesome name="star" color="#FFBA5A" size={12} />
<Text style={{ marginLeft: 4, color: '#FFBA5A' }}>3.5</Text>
</View>
<View style={styles.campingInfo}>
<FontAwesome name="location-arrow" color="#FF7657" size={12} />
<Text style={{ marginLeft: 4, color: '#FF7657' }}>3.0miles</Text>
</View>
<View style={styles.campingInfo}>
<Ionicons name="md-pricetag" color="black" size={12} />
<Text style={{ marginLeft: 4, color: 'black' }}>Free</Text>
</View>
</View>
</View>
</View>
Here, we have a parent View
component enclosing two child View
components. The first child View
component is reserved for Image
component. The second View
component is reserved for the details section inside the list item. The second View
component consists of several child View
components with style. And these View
components wrap the Icon
components as well as Text
components.
As we can see in the code snippet above, there are several style bindings in each View
component. Some are inline styles and some are styles from Stylesheet
component. The style from the Stylesheet
component is provided in the code snippet below:
camping: {
flex: 1,
flexDirection: 'row',
borderBottomColor: '#A5A5A5',
borderBottomWidth: 0.5,
padding: 20,
},
campingDetails: {
flex: 2,
paddingLeft: 20,
flexDirection: 'column',
justifyContent: 'space-around',
},
campingInfo: {
flexDirection: 'row',
alignItems: 'center',
marginRight: 14,
},
Hence, we will get the following result in our emulator screen:
As we can see, we have got the proper but incomplete list item in the emulator screen. Incomplete because we still need to add the Image to the left and a menu icon to the right. So, let us get on with adding the menu button to the right first.
Adding Vertical Option Menu button
Here, we are going to add a menu button that has a vertical options icon. The icon we want to include is not available in the FontAwesome
or Ionicons
icon package. So, we need to import one more icon package that is SimpleLineIcons
icon package from vector icons package as shown in the code snippet below:
import { FontAwesome , Ionicons, SimpleLineIcons} from '@expo/vector-icons';
Now, we are going to make use of SimpleLineIcons
package to add a vertical option icon menu button at the right. In order to do that, we need to add one more View
component inside the second child View
component of the renderList()
as shown in the code snippet below:
<View style={styles.campingDetails}>
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center' }}>
<Text style={{ fontSize: 14, fontWeight: 'bold' }}>
Camping title
</Text>
<Text style={{ fontSize: 12, color: '#A5A5A5', paddingTop: 5 }}>
Camping description
</Text>
</View>
<View style={{ flex: 1, flexDirection: 'row', }}>
<View style={styles.campingInfo}>
<FontAwesome name="star" color="#FFBA5A" size={12} />
<Text style={{ marginLeft: 4, color: '#FFBA5A' }}>3.5</Text>
</View>
<View style={styles.campingInfo}>
<FontAwesome name="location-arrow" color="#FF7657" size={12} />
<Text style={{ marginLeft: 4, color: '#FF7657' }}>3.0miles</Text>
</View>
<View style={styles.campingInfo}>
<Ionicons name="md-pricetag" color="black" size={12} />
<Text style={{ marginLeft: 4, color: 'black' }}>Free</Text>
</View>
</View>
</View>
<View style={{ flex: 0.2, justifyContent: 'center' }}>
<SimpleLineIcons name="options-vertical" color="#A5A5A5" size={24} />
</View>
</View>
Here, we have added the View
component wrapping the SimpleLineIcons
component which has the icon nameoptions-verticle
with some color
and size
props.
Hence, we get the following result in our emulator screen:
As we can see, we have got the options button on the right side of the list item. Now, we are going to replace the manual placeholder data with the mock data that we defined earlier in the campings
array.
Integrating Mock data
In this step, we are going to integrate accurate data to accurate placeholders in the list item template. Since we have an array with two objects, we are going to iterate through the array using map()
array function available in react-native. The map()
function allows us to iterate through each item in an array and return the required template. The parent View
component inside the map()
function will take on a unique id known as key
which will identify each list item uniquely. Now, to implement the map()
array function and iterate through the array which will return the template for each item with mock data, we need to use the code provided in the code snippet below into our renderList()
method:
return campings.map(
camping => {
return (
<View key={`camping-${camping.id}`} style={styles.camping}>
<View>
<Image />
</View>
<View style={styles.campingDetails}>
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center' }}>
<Text style={{ fontSize: 14, fontWeight: 'bold' }}>
{camping.name}
</Text>
<Text style={{ fontSize: 12, color: '#A5A5A5', paddingTop: 5 }}>
{camping.description}
</Text>
</View>
<View style={{ flex: 1, flexDirection: 'row', }}>
<View style={styles.campingInfo}>
<FontAwesome name="star" color="#FFBA5A" size={12} />
<Text style={{ marginLeft: 4, color: '#FFBA5A' }}>{camping.rating}</Text>
</View>
<View style={styles.campingInfo}>
<FontAwesome name="location-arrow" color="#FF7657" size={12} />
<Text style={{ marginLeft: 4, color: '#FF7657' }}>{camping.distance} miles</Text>
</View>
<View style={styles.campingInfo}>
<Ionicons name="md-pricetag" color="black" size={12} />
<Text style={{ marginLeft: 4, color: 'black' }}>{camping.price}</Text>
</View>
</View>
</View>
<View style={{ flex: 0.2, justifyContent: 'center' }}>
<SimpleLineIcons name="options-vertical" color="#A5A5A5" size={24} />
</View>
</View>
)
})
Therefore, we will get following result in our emulator screen:
As we can see, we have successfully implemented the list section containing two list items. The list items emphasize the camping spots around the map in an actual app. But, we still need to include the image of the camping spots. So now, let us work on including the image.
Including Image in the List
In this step, we are going to work on an image that is to be included on the left side of the list item. We have already separated a child View
component inside the parent View
component of renderList()
method in which we have defined an Image
component. Now, we are going to provide the source and some style properties to that Image component as shown in the code snippet below:
<View key={`camping-${camping.id}`} style={styles.camping}>
<View style={{flex : 1, overflow: 'hidden'}}>
<Image
style={styles.campingImage}
source={{ uri: camping.image }}
/>
</View>
The required style is provided in the code snippet below:
campingImage: {
width: width * 0.30,
height: width * 0.25,
borderRadius: 6,
},
Hence, we will get the following result in our emulator simulation:
<!--[if lt IE 9]>document.createElement('video');<![endif]-->
As we can see in the simulation above, we have got the image on the left side and the scrolling event also works properly. But the image style does not exactly match the image style in the actual app. So, we are going to make some small changes to the Image
component in order to make it exactly like that in actual Camping Spot Finder app.
Changing Image component to ImageBackground
Here, we are going to replace the Image
component with ImageBackground
component. The ImageBackground
component is a synonym to the background-image
property of CSS on the web. <ImageBackground>
component has the same props as the Image
component and enables us to add whatever children to it which we would like to layer on top of it. But first, we need to import the ImageBackground
component from the react-native package as shown in the code snippet below:
import { ImageBackground, Image, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, View, Dimensions, SafeAreaView } from 'react-native';
Now, we need to add the ImageBackground
component in place of Image
component and use required props and styles as shown in the code snippet below:
Now, the image in the list section looks similar to that in the actual app. With this, we have successfully completed the implementation of the list section in our Camping Spot Finder App UI clone. The list with the information about the camping sites appears just like in the actual app.
Now, we are going to prepare a small pre-requisite for the next part of this tutorial series. That is to implement navigation to the settings screen.
Navigation to the Settings screen
This step is a small pre-requisite for our next part of this tutorial series. In this step, we are simply going to add navigation to the settings screen in the settings icon button we created in the header section. We have already set up the TouchableOpacity
component to the settings button in the header section inside the renderHeader()
function. Now, we are going to add a navigation control to navigate to the settings screen in the onPress
event of the TouchableOpacity
component as shown in the code snippet below:
<View style={styles.settings}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('Settings')}>
<Ionicons name="ios-settings" size={24} color="black" />
</TouchableOpacity>
</View>
Since our Campings screen is already set up in the navigator stack, the navigation
instance that provides navigate()
function is readily available to us in the prop
variable. So, by using the navigate()
function with parameter as ‘Settings’, we can navigate to Settings screen just by clicking on the settings button on the header section as shown in the emulator simulation below:
Finally, we have successfully implemented the list section as well as navigation to the Settings screen in our Camping Spot Finder App UI clone.
Conclusion
This tutorial is the second part of the Camping Spot Finder App UI clone tutorial series. In this part, we continued from where we left off in the first part of this tutorial series. In the part of the tutorial, we first learned how to make use of SafeAreaView
component. Then, we learned how to integrate the mock data into the template using map()
array function. We also learned about one new component that is ImageBackground
component that we imported from react-native package to place the image properly on the list section. Lastly, we got an insight on how to use navigate()
function provided by navigation
instance available in prop
variable to navigate to the Settings screen.
In the next part, we are going to implement the different components of the Settings screen in our Camping Spots Finder App UI clone.
So, Stay Tuned folks!!
The post Camping Spots Finder App UI Clone with React Native #2 : List Section appeared first on Kriss.
Disclosure
This post includes affiliate links; I may receive compensation if you purchase
products or services from different links provided in this article
Posted on October 12, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.