DEV Community

Cover image for Camping Spots Finder App UI Clone with React Native # 2: List Section
absek
absek

Posted on • Originally published at kriss.io on

Camping Spots Finder App UI Clone with React Native # 2: List Section

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 SafeAreaViewcomponent 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(&#39;video&#39;);<![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

Top comments (0)